RGB color conversion

Страница 2/3
1 | | 3

By Grauw

Ascended (10720)

Аватар пользователя Grauw

27-09-2015, 22:59

NYYRIKKI wrote:

@Grauw If you want to take that approach then (VALUE+16)/32 is better... The problem is that you think that 255 should become 7 while actually you should think that 256 should become 8.

No, that way 8-bit values 0-47 translate to 3-bit value 0, you get way too much error there.

Simplifying the problem to grayscale, black is black and white is white. So the 8-bit (0-255) values are on a different scale than the 3-bit (0-7) values, they can’t be converted by simply dropping bits, you need to consider them on a linear scale as 0-1 where 0 is black and 1 is white.

The linear scale for 3-bit values is: 0.0, 0.143, 0.286, 0.429, 0.571, 0.714, 0.857, 1.0.

The linear scale for 8-bit values I’ll let you generate by yourself Smile. But, for each value on the 8-bit scale, you need to pick the 3-bit scale’s value that is closest, in order to minimise the error.

By NYYRIKKI

Enlighted (6033)

Аватар пользователя NYYRIKKI

27-09-2015, 22:58

Ok yes, I was wrong...

By RetroTechie

Paragon (1563)

Аватар пользователя RetroTechie

27-09-2015, 23:02

mars2000you wrote:

There's probably a better solution : screen 8 with his 256 colors ! Smile

Why degrad the colors to fit in screen 5 or 7 ?

Palette colors are fewer in number, but have a little bit more accuracy than screen 8 RGB values (to be exact: 1 bit extra for the blue value). So depending on input, conversion to screen 5 or 7 may provide better result than conversion to screen 8. Well okay - probably not for most images... Smile2

If output as YJK data is allowed, then you can get much better results. Conversion formulas for this are in the V9958 data book.

Btw. good info there, Grauw! Smile

By AxelStone

Prophet (3193)

Аватар пользователя AxelStone

27-09-2015, 23:06

It's very easy: in true color, RGB goes from 0 to 255(256 levels), in MSX2 RGB goes from 0 to 7 (8 levels). To convert true color into MSX2 image, simply divide by 32 its 3 components:

RGB: 255, 153, 0
MSX2: 7, 4, 0

It's recommended a manual revision in order to get best aproximation, this is, perhaps in the example yo prefer something like 7,3,0 or 7,5,0 depending your image.

By Grauw

Ascended (10720)

Аватар пользователя Grauw

27-09-2015, 23:32

@AxelStone: So, you’re saying 8-bit colour (255, 224, 31) should convert to 3-bit colour (7, 7, 0)? As I elaborated above it should actually convert to (7, 6, 1). It becomes clear when you convert them to linear values in the range 0-1:

(255, 224, 31) -> (1.00, 0.88, 0.12)

(7, 7, 0) -> (1.00, 1.00, 0.00), error: (0.0, +0.12, -0.12)
(7, 6, 1) -> (1.00, 0.86, 0.14), error: (0.0, -0.02, +0.02)

As you can see, the value (7, 6, 1) is much closer to the actual colour represented by the 8-bit values. Therefore, divide-by-32 is not a good solution. In stead, divide-by-(255/7).

Consider that (0, 0, 0) is fully black in both scales, and (7, 7, 7) and (255, 255, 255) are fully white. Also consider the conversion from 3-bit values to 8-bit values. Does value 7 convert to 224, or to 255?

By AxelStone

Prophet (3193)

Аватар пользователя AxelStone

27-09-2015, 23:39

@Grauw But your aproximation of /32 is not well done: (255,224,31) / 32 = (7.9, 7, 0.96)

For me, 0.96 is clearly 1, so my first try should be (7,7,1), not (7,7,0). In the same point, 224 is in the limit. 255-224=31, so it seems wrong asign same color to 2 values separated by 31. The common sense is saying you "hey, they are not the same color", so most probably you should choose 6 not 7. In other words, you finally has selected (7,6,1) simply using human hand for final retouch.

You can see that even your method doesn't works if you don't apply human retouch: 255/7=36.4, if you divide 31/36.4 you get 0.85, so 3rd value (31) is even furhter from 1 than using /32 where you get 0.96.

In other words, whenever technique you could use, the human hand is finally needed.

By Grauw

Ascended (10720)

Аватар пользователя Grauw

28-09-2015, 00:49

AxelStone wrote:

@Grauw But your aproximation of /32 is not well done: (255,224,31) / 32 = (7.9, 7, 0.96)

But, 7 is the maximum value, so how can there be a value 7.9? I was assuming you were rounding down, but if you’re rounding normally, then 7.9 should become 8? Because 8 does not exist, it’s set to 7, introducing a new +0.13 error. The error should never get above 0.071 (= 1 / 7 / 2), if it does the colour is misallocated.

Colour (7, 7, 7) is the same as (255, 255, 255), both fully white. So, 255 must translate to 7.0, not 7.9. You are saying on PC there is a colour whiter than white? Or that (7, 7, 7) on the MSX is not actually white, but light gray?

Try to do the conversion the other way around. What is the 24-bit RGB value of (7, 3, 0)?

By NYYRIKKI

Enlighted (6033)

Аватар пользователя NYYRIKKI

28-09-2015, 01:06

Uh... From the first post I could not see this coming such a big conversation Smile

By AxelStone

Prophet (3193)

Аватар пользователя AxelStone

28-09-2015, 11:07

Grauw wrote:

Try to do the conversion the other way around. What is the 24-bit RGB value of (7, 3, 0)?

Mmm perhaps you are right, your method needs less "human retouch" Tongue .

By hit9918

Prophet (2927)

Аватар пользователя hit9918

28-09-2015, 23:34

NYYRIKKI wrote:

Uh... From the first post I could not see this coming such a big conversation Smile

But it hasn't yet taken into acount the nonlinear DAC levels Big smile
In the below code I got them in that l() function, I forgot from where I got them?

At the begining the differences between DAC levels are printed.
32, 40, 32, 40... mhm was that again about hardware savings or is it a trick suiting artists purposes?
some colors are in more harsh distance than 36, some are a more closer pack.

how does this fit a linear sheme of 9958 VUY mode - the 32,40,32,40 jumps would fit into a linear 5bit DAC, I assume things look identic on 9958.
the levels

function l(n) {
	c = new Array();
c[0] = 0x06;
c[1] = 0x20;
c[2] = 0x48;
c[3] = 0x68;
c[4] = 0x90;
c[5] = 0xb0;
c[6] = 0xd8;
c[7] = 0xf7;
	return c[n];
}

the diffs:
0-1: 26
1-2: 40
2-3: 32
3-4: 40
4-5: 32
5-6: 40
6-7: 31

the html file showing the colors demo


function hex(n) {
	n1 = n / 16; n2 = n%16;
	s = "0123456789abcdef";
	return "" + s.charAt(n1) + s.charAt(n2)
}

function l(n) {
	c = new Array();
c[0] = 0x06;
c[1] = 0x20;
c[2] = 0x48;
c[3] = 0x68;
c[4] = 0x90;
c[5] = 0xb0;
c[6] = 0xd8;
c[7] = 0xf7;
	return c[n];
}


for (i = 0; i < 7; i++) { document.write(''+i+'-'+(i+1)+': '+(l(i+1)-l(i))+'<br>'); }

document.write('<table border="0" cellspacing="32" cellpadding="0"><tr><td>');
document.write('<table border="0" cellspacing="0" cellpadding="0"><tr>');

for (g = 0; g <= 7; g++) {
	document.write("<tr>");
	for (b = 0; b <= 7; b++) {
		for (r = 0; r <= 7; r++) {
			document.write('<td width="16" height="16">');
			document.write(" ");
			document.write("</td>");
		}
	}
	document.write("</tr>");
}

document.write('</tr><table>');
document.write('</td></tr><table>');

Страница 2/3
1 | | 3