Convert 3-byte RGB to 3-3-2

Topics related to the API, programming discussions & questions, coding tips, bugs, etc. should go here.
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Convert 3-byte RGB to 3-3-2

Post by nicksen782 »

I've been reading through the forums and I cannot seem to find what I am looking for.

Posts that seemed useful:
http://uzebox.org/forums/viewtopic.php? ... =dac#p1174
http://uzebox.org/forums/viewtopic.php? ... =dac#p1174

However I do not get the values back that I wanted.

I have the R, G, B values for a color. This is 3 bytes per color. I want to convert from the 3 byte to the 3bit-3bit-2bit type.

If I take 221, 255, 255 (the transparent color that is stored in a gconvert.inc file as 0xFE) I should be able to get 0xFE. I instead get 0xFF, 0xDF, etc. This should be something trivial.
User avatar
uze6666
Site Admin
Posts: 4801
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

Re: Convert 3-byte RGB to 3-3-2

Post by uze6666 »

Try this formula :

U8 index=(red&0xe0)+((green>>3)&0x1c)+(blue>>6);
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Re: Convert 3-byte RGB to 3-3-2

Post by nicksen782 »

Code: Select all

function encode332(R, G, B){
	// R=221;G=255;B=255;
	var index=(R&0xe0)+((G>>3)&0x1c)+(B>>6);
	return index.toString(16);
}
Returns 233 or 0xDF. Does not return the expected 0xFE. Shouldn't I be able to convert the values to 0xFE?

Each color has a value that the Uzebox should understand. For example, 221, 255, 255 is the transparent color and would be stored in a Gconvert .inc file as 0xFE. In my program you can pick color values from a palette and the color and hex values are visible. I literally just have it where the color clicked on the palette is copied as a usable color.

Here is a visual example of what I am doing. Please notice that the hex values displayed are wrong with the exception of the black and white. I can confirm that the values for RGB sent are 221, 255, 255 as I can hard-code it right into the function.
Screenshot 2015-03-27 at 3.15.16 PM.png
Screenshot 2015-03-27 at 3.15.16 PM.png (31.24 KiB) Viewed 4805 times
User avatar
uze6666
Site Admin
Posts: 4801
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

Re: Convert 3-byte RGB to 3-3-2

Post by uze6666 »

Oops, I've put the color components in the wrong order! If you looks at the schematic, red is the lsbits.

Code: Select all

index=(Blue&0xc0)+((Green>>2)&0x38)+(Red>>5);

Code: Select all

B=0b11111111 -> 11000000
G=0b11111111 -> 00111000
R=0b11011101 -> 00000110
                --------
                11111110 = 0xFE
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Re: Convert 3-byte RGB to 3-3-2

Post by nicksen782 »

Thank you! Output is now as expected. This is all part of a tile editor that I am building.

Encore? How do you do the reverse to convert the 0xFE back to 211, 255, 255?
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Re: Convert 3-byte RGB to 3-3-2

Post by nicksen782 »

I tried to get the 3 bytes from the 3-3-2 byte.
nR = (((index >> 0) & 0x07) * (255/7)) ; // 3 bits
nG = (((index >> 3) & 0x07) * (255/7)) ; // 3 bits
nB = (((index >> 6) & 0x03) * (255/3)) ; // 2 bits

These are my results: 218.57142857142858, 255, 255. The red value is wrong. It should be 221. I'm thinking there is a loss of color resolution here but 0xFE is a known value and I'm a bit surprised.

I need to be able to go back and forth between RGB and 3-3-2. If I only use colors supported by the Uzebox palette, I should be able to, right?
User avatar
uze6666
Site Admin
Posts: 4801
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

Re: Convert 3-byte RGB to 3-3-2

Post by uze6666 »

I tried to get the 3 bytes from the 3-3-2 byte.
nR = (((index >> 0) & 0x07) * (255/7)) ; // 3 bits
nG = (((index >> 3) & 0x07) * (255/7)) ; // 3 bits
nB = (((index >> 6) & 0x03) * (255/3)) ; // 2 bits
The above formulas are not exactly right. It models the initial R-2R resistor dac (only used in my prototype) where the blue component was spread evenly. Clay Cowgill weighted DAC works a bit differently, the blue channel is modeled like it's 3 bit but the lsbit is always zero. This results in even white levels, but also means the blue channel can never be 255. Here the right formulas:

Code: Select all

R= (byte)((((index>>0) & 7) * 255 /7))  ; //red			
G= (byte)((((index>>3) & 7) * 255 /7))  ; //green				
B= (byte)((((index>>5) & 6) * 255 /7))  ;  //blue
The bad news is that the .ACT palette and color tables in the /gfx directory are wrong and modeled against the old dac (all these years to find out!). The good news is that the difference are pretty subtle and that I have regenerated it. I'll commit it to github shorty.

Using the above formulas, 0xFE is now RGB=(218,255,218).
Attachments
uzebox-palette.zip
(475 Bytes) Downloaded 203 times
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Re: Convert 3-byte RGB to 3-3-2

Post by nicksen782 »

Okay great! That solved the issue. I used the old algorithm with my inc2img program as well. I'll fix that too.

I see the attached .ACT file. It is not a graphic so I'll check out Github later. I'll need the new graphic.

Thanks again for your help, Uze.

The code is JavaScript. It would be very easy to convert to C. Here it is for any whom are interested. I used the parseInt function to remove the decimal portion of the number.

Code: Select all

function encode332(R, G, B){
	// Convert the RGB value to 3-3-2 RBG.
	var index=(B&0xc0) + ((G>>2)&0x38) + (R>>5);

	// Convert the value back.
	var nR=  ( ( ( ( index>>0) & 7) * (255 /7) ) ) ; // red
	var nG=  ( ( ( ( index>>3) & 7) * (255 /7) ) ) ; // green
	var nB=  ( ( ( ( index>>5) & 6) * (255 /7) ) ) ; // blue

	// Output all values
	console.log('8-bit RGB:', index, 'or 0x'+index.toString(16).toUpperCase(), '. 24-bit RGB:', 'R='+parseInt(nR, 10), 'G='+parseInt(nG, 10), 'B='+parseInt(nB, 10));

	// Return the 3-3-2 RGB value as hex.
	return index.toString(16);
}
User avatar
kivan117
Posts: 73
Joined: Sat Mar 14, 2015 5:43 am

Re: Convert 3-byte RGB to 3-3-2

Post by kivan117 »

Your program looks pretty handy nicksen782. Having a tile editor targeted specifically at the Uzebox would definitely speed up the graphics creation pipeline when working on games. At least for me. The current method I use is a bit of juggling GIMP's terrible interface, hand typing out a new xml, then running the cli gconvert, then going into the generated text and splitting it into different files for my own organization, occasionally editing the text by hand for minor tweaks . Doing that repeatedly every time I want to make a small change or add one tile can really be a hassle. It works just fine, but it's slow and can be daunting for newcomers. Can't wait to see what comes of your work.
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Re: Convert 3-byte RGB to 3-3-2

Post by nicksen782 »

Thank you for the words of encouragement!
Post Reply