xref: /plan9/sys/src/cmd/unix/drawterm/libdraw/rgb.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <libc.h>
3*8ccd4a63SDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier 
5*8ccd4a63SDavid du Colombier /*
6*8ccd4a63SDavid du Colombier  * This original version, although fast and a true inverse of
7*8ccd4a63SDavid du Colombier  * cmap2rgb, in the sense that rgb2cmap(cmap2rgb(c))
8*8ccd4a63SDavid du Colombier  * returned the original color, does a terrible job for RGB
9*8ccd4a63SDavid du Colombier  * triples that do not appear in the color map, so it has been
10*8ccd4a63SDavid du Colombier  * replaced by the much slower version below, that loops
11*8ccd4a63SDavid du Colombier  * over the color map looking for the nearest point in RGB
12*8ccd4a63SDavid du Colombier  * space.  There is no visual psychology reason for that
13*8ccd4a63SDavid du Colombier  * criterion, but it's easy to implement and the results are
14*8ccd4a63SDavid du Colombier  * far more pleasing.
15*8ccd4a63SDavid du Colombier  *
167dd7cddfSDavid du Colombier int
177dd7cddfSDavid du Colombier rgb2cmap(int cr, int cg, int cb)
187dd7cddfSDavid du Colombier {
197dd7cddfSDavid du Colombier 	int r, g, b, v, cv;
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier 	if(cr < 0)
227dd7cddfSDavid du Colombier 		cr = 0;
237dd7cddfSDavid du Colombier 	else if(cr > 255)
247dd7cddfSDavid du Colombier 		cr = 255;
257dd7cddfSDavid du Colombier 	if(cg < 0)
267dd7cddfSDavid du Colombier 		cg = 0;
277dd7cddfSDavid du Colombier 	else if(cg > 255)
287dd7cddfSDavid du Colombier 		cg = 255;
297dd7cddfSDavid du Colombier 	if(cb < 0)
307dd7cddfSDavid du Colombier 		cb = 0;
317dd7cddfSDavid du Colombier 	else if(cb > 255)
327dd7cddfSDavid du Colombier 		cb = 255;
337dd7cddfSDavid du Colombier 	r = cr>>6;
347dd7cddfSDavid du Colombier 	g = cg>>6;
357dd7cddfSDavid du Colombier 	b = cb>>6;
367dd7cddfSDavid du Colombier 	cv = cr;
377dd7cddfSDavid du Colombier 	if(cg > cv)
387dd7cddfSDavid du Colombier 		cv = cg;
397dd7cddfSDavid du Colombier 	if(cb > cv)
407dd7cddfSDavid du Colombier 		cv = cb;
417dd7cddfSDavid du Colombier 	v = (cv>>4)&3;
427dd7cddfSDavid du Colombier 	return ((((r<<2)+v)<<4)+(((g<<2)+b+v-r)&15));
437dd7cddfSDavid du Colombier }
44*8ccd4a63SDavid du Colombier */
45*8ccd4a63SDavid du Colombier 
46*8ccd4a63SDavid du Colombier int
rgb2cmap(int cr,int cg,int cb)47*8ccd4a63SDavid du Colombier rgb2cmap(int cr, int cg, int cb)
48*8ccd4a63SDavid du Colombier {
49*8ccd4a63SDavid du Colombier 	int i, r, g, b, sq;
50*8ccd4a63SDavid du Colombier 	ulong rgb;
51*8ccd4a63SDavid du Colombier 	int best, bestsq;
52*8ccd4a63SDavid du Colombier 
53*8ccd4a63SDavid du Colombier 	best = 0;
54*8ccd4a63SDavid du Colombier 	bestsq = 0x7FFFFFFF;
55*8ccd4a63SDavid du Colombier 	for(i=0; i<256; i++){
56*8ccd4a63SDavid du Colombier 		rgb = cmap2rgb(i);
57*8ccd4a63SDavid du Colombier 		r = (rgb>>16) & 0xFF;
58*8ccd4a63SDavid du Colombier 		g = (rgb>>8) & 0xFF;
59*8ccd4a63SDavid du Colombier 		b = (rgb>>0) & 0xFF;
60*8ccd4a63SDavid du Colombier 		sq = (r-cr)*(r-cr)+(g-cg)*(g-cg)+(b-cb)*(b-cb);
61*8ccd4a63SDavid du Colombier 		if(sq < bestsq){
62*8ccd4a63SDavid du Colombier 			bestsq = sq;
63*8ccd4a63SDavid du Colombier 			best = i;
64*8ccd4a63SDavid du Colombier 		}
65*8ccd4a63SDavid du Colombier 	}
66*8ccd4a63SDavid du Colombier 	return best;
67*8ccd4a63SDavid du Colombier }
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier int
cmap2rgb(int c)707dd7cddfSDavid du Colombier cmap2rgb(int c)
717dd7cddfSDavid du Colombier {
727dd7cddfSDavid du Colombier 	int j, num, den, r, g, b, v, rgb;
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier 	r = c>>6;
757dd7cddfSDavid du Colombier 	v = (c>>4)&3;
767dd7cddfSDavid du Colombier 	j = (c-v+r)&15;
777dd7cddfSDavid du Colombier 	g = j>>2;
787dd7cddfSDavid du Colombier 	b = j&3;
797dd7cddfSDavid du Colombier 	den=r;
807dd7cddfSDavid du Colombier 	if(g>den)
817dd7cddfSDavid du Colombier 		den=g;
827dd7cddfSDavid du Colombier 	if(b>den)
837dd7cddfSDavid du Colombier 		den=b;
847dd7cddfSDavid du Colombier 	if(den==0) {
857dd7cddfSDavid du Colombier 		v *= 17;
867dd7cddfSDavid du Colombier 		rgb = (v<<16)|(v<<8)|v;
877dd7cddfSDavid du Colombier 	}
887dd7cddfSDavid du Colombier 	else{
897dd7cddfSDavid du Colombier 		num=17*(4*den+v);
907dd7cddfSDavid du Colombier 		rgb = ((r*num/den)<<16)|((g*num/den)<<8)|(b*num/den);
917dd7cddfSDavid du Colombier 	}
927dd7cddfSDavid du Colombier 	return rgb;
937dd7cddfSDavid du Colombier }
947dd7cddfSDavid du Colombier 
957dd7cddfSDavid du Colombier int
cmap2rgba(int c)967dd7cddfSDavid du Colombier cmap2rgba(int c)
977dd7cddfSDavid du Colombier {
987dd7cddfSDavid du Colombier 	return (cmap2rgb(c)<<8)|0xFF;
997dd7cddfSDavid du Colombier }
100