xref: /inferno-os/libdraw/rgb.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 #include "lib9.h"
2 #include "draw.h"
3 
4 /*
5  * This original version, although fast and a true inverse of
6  * cmap2rgb, in the sense that rgb2cmap(cmap2rgb(c))
7  * returned the original color, does a terrible job for RGB
8  * triples that do not appear in the color map, so it has been
9  * replaced by the much slower version below, that loops
10  * over the color map looking for the nearest point in RGB
11  * space.  There is no visual psychology reason for that
12  * criterion, but it's easy to implement and the results are
13  * far more pleasing.
14  *
15 int
16 rgb2cmap(int cr, int cg, int cb)
17 {
18 	int r, g, b, v, cv;
19 
20 	if(cr < 0)
21 		cr = 0;
22 	else if(cr > 255)
23 		cr = 255;
24 	if(cg < 0)
25 		cg = 0;
26 	else if(cg > 255)
27 		cg = 255;
28 	if(cb < 0)
29 		cb = 0;
30 	else if(cb > 255)
31 		cb = 255;
32 	r = cr>>6;
33 	g = cg>>6;
34 	b = cb>>6;
35 	cv = cr;
36 	if(cg > cv)
37 		cv = cg;
38 	if(cb > cv)
39 		cv = cb;
40 	v = (cv>>4)&3;
41 	return ((((r<<2)+v)<<4)+(((g<<2)+b+v-r)&15));
42 }
43 */
44 
45 int
rgb2cmap(int cr,int cg,int cb)46 rgb2cmap(int cr, int cg, int cb)
47 {
48 	int i, r, g, b, sq;
49 	ulong rgb;
50 	int best, bestsq;
51 
52 	best = 0;
53 	bestsq = 0x7FFFFFFF;
54 	for(i=0; i<256; i++){
55 		rgb = cmap2rgb(i);
56 		r = (rgb>>16) & 0xFF;
57 		g = (rgb>>8) & 0xFF;
58 		b = (rgb>>0) & 0xFF;
59 		sq = (r-cr)*(r-cr)+(g-cg)*(g-cg)+(b-cb)*(b-cb);
60 		if(sq < bestsq){
61 			bestsq = sq;
62 			best = i;
63 		}
64 	}
65 	return best;
66 }
67 
68 int
cmap2rgb(int c)69 cmap2rgb(int c)
70 {
71 	int j, num, den, r, g, b, v, rgb;
72 
73 	r = c>>6;
74 	v = (c>>4)&3;
75 	j = (c-v+r)&15;
76 	g = j>>2;
77 	b = j&3;
78 	den=r;
79 	if(g>den)
80 		den=g;
81 	if(b>den)
82 		den=b;
83 	if(den==0) {
84 		v *= 17;
85 		rgb = (v<<16)|(v<<8)|v;
86 	}
87 	else{
88 		num=17*(4*den+v);
89 		rgb = ((r*num/den)<<16)|((g*num/den)<<8)|(b*num/den);
90 	}
91 	return rgb;
92 }
93 
94 int
cmap2rgba(int c)95 cmap2rgba(int c)
96 {
97 	return (cmap2rgb(c)<<8)|0xFF;
98 }
99