Mixing Two 16 Bits Colors


kouky

Member
Joined
Sep 3, 2006
Messages
185
Location
London
Website
www.caou.org
I've written some code to mix 2 16bits colors together.
Imagine 2 photoshop layers, the top one is 50% alpha, my code is doing that.
So here's the code to calculate the merged color between couleur16A and couleur16B.
Code:
				couleur16A=koukyTiles16[iii];
				couleurRA=couleur16A>>11;
				couleurVA=(couleur16A&(0x7E0))>>5;
				couleurBA=couleur16A&0x1F;

				couleur16B=koukyTiles16[iii+screenWH];
				couleurRB=couleur16B>>11;
				couleurVB=(couleur16B&(0x7E0))>>5;
				couleurBB=couleur16B&0x1F;
			finalTiles16[iii]=((couleurRA+couleurRB)>>1<<11)+((couleurVA+couleurVB)>>1<<5)+((couleurBA+couleurBB)>>1);
I believe it can be improved to run faster, but how? :unsure:
 
use the -funroll-loops flag (I think thats what its called). Also make the loop so it goes back from the end instead of forward from the beginning, as subtraction is faster than addition.
 
I believe it can be improved to run faster, but how? :unsure:

I think this is what you want.

Code:
INLINE  u32 gpuBlending00(u32 uDst, u32 uSrc)
{
  return (((uDst & 0x7BDE) + (uSrc & 0x7BDE)) >> 1);
}

You also can improve futher if you do 2 colors at a time, just use a 0x7bde7bde mask nad put two colors at each entry value.
 
Last edited by a moderator:
thank Blah, I will make a search aroung funrolls.

una-i,
I got an error about this line when I compile:
INLINE u32 gpuBlending00(u32 uDst, u32 uSrc)

1 C:\pikix\rendering16.h expected constructor, destructor, or type conversion before "unsigned"
1 C:\pikix\rendering16.h expected `,' or `;' before "unsigned"

any suggestion ?
 
by the sounds of that error you don't have INLINE defined so just remove it and it should work
 
Then it wouldn't be inline, now would it. Oh yeah, and if you need a good C/C++ book, try Thinking in C++ (its free).
 
Then it wouldn't be inline, now would it. Oh yeah, and if you need a good C/C++ book, try Thinking in C++ (its free).

I meant that it looks like INLINE wasnt defined and if he removed it, it should compile.
You could just replace that INLINE with a lowercase inline which should do the same thing
 
Last edited by a moderator:
With a lowercase inline, it compiled ok, the result is not OK.
The formula must be wrong :/
I will try to correct it
 
Well, as you're using 565 instead of 555 the value should probably be F7DE.
Also you might want to shift each value before adding them incase you get an overflow.
 
I maybe wasn't clear.
I am suggesting:

Code:
finalTiles16[iii] = ((koukyTiles16[iii] & 0xF7DE) >> 1) + ((koukyTiles16[iii+screenWH] & 0xF7DE) >> 1);

That should work?
 
I maybe wasn't clear.
I am suggesting:

Code:
finalTiles16[iii] = ((koukyTiles16[iii] & 0xF7DE) >> 1) + ((koukyTiles16[iii+screenWH] & 0xF7DE) >> 1);

That should work?

I think so, my "previous" mask was from psx4al and uses 555 psx color format :p.

You only need the "per color shift" in case you do two 16bit colors at once packed in a 32bit unsigned.
 
Last edited by a moderator:
You only need the "per color shift" in case you do two 16bit colors at once packed in a 32bit unsigned.

This is correct.
In any case, if the compilier optimized correctly the shifts should be free on gp2x. However I don't think any of the prebuilt compiliers know this optimization for arm yet? oh well.
 
Last edited by a moderator:
No I ould like to make the "add" photoshop effect:
I tried
finalTiles16[iii] = (koukyTiles16[iii]) | (koukyTiles16[iii+screenWH]);

but it didn't work, too bad :/
 
I've found a solution:

Code:
		unsigned short r1,v1,b1;
		for (iii=0;iii<screenWH;iii++)
		{

		b1=(koukyTiles16[iii]& 31)+(koukyTiles16[iii+screenWH]& 31);
		v1=(  (koukyTiles16[iii]& (63*32))	 )+(  (koukyTiles16[iii+screenWH]& (63*32))	 )>>5;
		r1=(  (koukyTiles16[iii]& (31*64*32))  )+(  (koukyTiles16[iii+screenWH]& (31*64*32))  )>>11;
		
		if (b1>31)b1=31;
		if (v1>63)v1=63;
		if (r1>31)r1=31;

		finalTiles16[iii] =(b1)+ (v1<<5)+(r1<<11);
		}

but it's very heavy coding !
I wish I could optimise it
 
Well I guess you could cut out some stuff, but it seems this is just a slightly heavier operation.

Code:
		unsigned short r1,v1,b1;
		for (iii=0;iii<screenWH;iii++)
		{

		b1=(koukyTiles16[iii] & 0x001F) + (koukyTiles16[iii+screenWH] & 0x001F);
		v1=(koukyTiles16[iii] & 0x07E0) + (koukyTiles16[iii+screenWH] & 0x07E0);
		r1=(koukyTiles16[iii] & 0xF800) + (koukyTiles16[iii+screenWH] & 0xF800);
		
		if (b1>0x001F)b1=0x001F;
		if (v1>0x07E0)v1=0x07E0;
		if (r1>0xF800)r1=0xF800;

		finalTiles16[iii] = b1 | v1 | r1;
		}

Not much better, just got rid of the shifts because adding two variables won't make any bits appear lower down than the least significant bit. I also changed the values for hex so it reads a bit better.
 
Two variables won't make any bits appear lower, I agree, but they could make bit to appear higher, no ?
so that:
rgb 000 000 200 + rgb 000 000 100 = rgb 000 045 255,
which is very bad...
result shoud be rgb 000 000 255

For an obscure reason, your suggestion didn't gave good color results,but thanks for your time spent on my worry!
 
Back
Top