xref: /plan9/sys/src/cmd/vnc/color.c (revision f8e525ac91e3a7fae3f104837a69862dc348aa81)
1*9a747e4fSDavid du Colombier #include "vnc.h"
2*9a747e4fSDavid du Colombier #include "vncv.h"
3*9a747e4fSDavid du Colombier 
4*9a747e4fSDavid du Colombier enum {
5*9a747e4fSDavid du Colombier 	RGB12 = CHAN4(CIgnore, 4, CRed, 4, CGreen, 4, CBlue, 4),
6*9a747e4fSDavid du Colombier 	BGR12 = CHAN4(CIgnore, 4, CBlue, 4, CGreen, 4, CRed, 4),
7*9a747e4fSDavid du Colombier 	BGR8 = CHAN3(CBlue, 2, CGreen, 3, CRed, 3),
8*9a747e4fSDavid du Colombier };
9*9a747e4fSDavid du Colombier 
10*9a747e4fSDavid du Colombier void (*cvtpixels)(uchar*, uchar*, int);
11*9a747e4fSDavid du Colombier 
12*9a747e4fSDavid du Colombier static void
chan2fmt(Pixfmt * fmt,ulong chan)13*9a747e4fSDavid du Colombier chan2fmt(Pixfmt *fmt, ulong chan)
14*9a747e4fSDavid du Colombier {
15*9a747e4fSDavid du Colombier 	ulong c, rc, shift;
16*9a747e4fSDavid du Colombier 
17*9a747e4fSDavid du Colombier 	shift = 0;
18*9a747e4fSDavid du Colombier 	for(rc = chan; rc; rc >>=8){
19*9a747e4fSDavid du Colombier 		c = rc & 0xFF;
20*9a747e4fSDavid du Colombier 		switch(TYPE(c)){
21*9a747e4fSDavid du Colombier 		case CRed:
22*9a747e4fSDavid du Colombier 			fmt->red = (Colorfmt){(1<<NBITS(c))-1, shift};
23*9a747e4fSDavid du Colombier 			break;
24*9a747e4fSDavid du Colombier 		case CBlue:
25*9a747e4fSDavid du Colombier 			fmt->blue = (Colorfmt){(1<<NBITS(c))-1, shift};
26*9a747e4fSDavid du Colombier 			break;
27*9a747e4fSDavid du Colombier 		case CGreen:
28*9a747e4fSDavid du Colombier 			fmt->green = (Colorfmt){(1<<NBITS(c))-1, shift};
29*9a747e4fSDavid du Colombier 			break;
30*9a747e4fSDavid du Colombier 		}
31*9a747e4fSDavid du Colombier 		shift += NBITS(c);
32*9a747e4fSDavid du Colombier 	}
33*9a747e4fSDavid du Colombier }
34*9a747e4fSDavid du Colombier 
35*9a747e4fSDavid du Colombier /*
36*9a747e4fSDavid du Colombier  * convert 32-bit data to 24-bit data by skipping
37*9a747e4fSDavid du Colombier  * the last of every four bytes.  we skip the last
38*9a747e4fSDavid du Colombier  * because we keep the server in little endian mode.
39*9a747e4fSDavid du Colombier  */
40*9a747e4fSDavid du Colombier static void
cvt32to24(uchar * dst,uchar * src,int npixel)41*9a747e4fSDavid du Colombier cvt32to24(uchar *dst, uchar *src, int npixel)
42*9a747e4fSDavid du Colombier {
43*9a747e4fSDavid du Colombier 	int i;
44*9a747e4fSDavid du Colombier 
45*9a747e4fSDavid du Colombier 	for(i=0; i<npixel; i++){
46*9a747e4fSDavid du Colombier 		*dst++ = *src++;
47*9a747e4fSDavid du Colombier 		*dst++ = *src++;
48*9a747e4fSDavid du Colombier 		*dst++ = *src++;
49*9a747e4fSDavid du Colombier 		src++;
50*9a747e4fSDavid du Colombier 	}
51*9a747e4fSDavid du Colombier }
52*9a747e4fSDavid du Colombier 
53*9a747e4fSDavid du Colombier /*
54*9a747e4fSDavid du Colombier  * convert RGB12 (x4r4g4b4) into CMAP8
55*9a747e4fSDavid du Colombier  */
56*9a747e4fSDavid du Colombier static uchar rgb12[16*16*16];
57*9a747e4fSDavid du Colombier static void
mkrgbtab(void)58*9a747e4fSDavid du Colombier mkrgbtab(void)
59*9a747e4fSDavid du Colombier {
60*9a747e4fSDavid du Colombier 	int r, g, b;
61*9a747e4fSDavid du Colombier 
62*9a747e4fSDavid du Colombier 	for(r=0; r<16; r++)
63*9a747e4fSDavid du Colombier 	for(g=0; g<16; g++)
64*9a747e4fSDavid du Colombier 	for(b=0; b<16; b++)
65*9a747e4fSDavid du Colombier 		rgb12[r*256+g*16+b] = rgb2cmap(r*0x11, g*0x11, b*0x11);
66*9a747e4fSDavid du Colombier }
67*9a747e4fSDavid du Colombier 
68*9a747e4fSDavid du Colombier static void
cvtrgb12tocmap8(uchar * dst,uchar * src,int npixel)69*9a747e4fSDavid du Colombier cvtrgb12tocmap8(uchar *dst, uchar *src, int npixel)
70*9a747e4fSDavid du Colombier {
71*9a747e4fSDavid du Colombier 	int i, s;
72*9a747e4fSDavid du Colombier 
73*9a747e4fSDavid du Colombier 	for(i=0; i<npixel; i++){
74*9a747e4fSDavid du Colombier 		s = (src[0] | (src[1]<<8)) & 0xFFF;
75*9a747e4fSDavid du Colombier 		*dst++ = rgb12[s];
76*9a747e4fSDavid du Colombier 		src += 2;
77*9a747e4fSDavid du Colombier 	}
78*9a747e4fSDavid du Colombier }
79*9a747e4fSDavid du Colombier 
80*9a747e4fSDavid du Colombier /*
81*9a747e4fSDavid du Colombier  * convert BGR8 (b2g3r3, default VNC format) to CMAP8
82*9a747e4fSDavid du Colombier  * some bits are lost.
83*9a747e4fSDavid du Colombier  */
84*9a747e4fSDavid du Colombier static uchar bgr8[256];
85*9a747e4fSDavid du Colombier static void
mkbgrtab(void)86*9a747e4fSDavid du Colombier mkbgrtab(void)
87*9a747e4fSDavid du Colombier {
88*9a747e4fSDavid du Colombier 	int i, r, g, b;
89*9a747e4fSDavid du Colombier 
90*9a747e4fSDavid du Colombier 	for(i=0; i<256; i++){
91*9a747e4fSDavid du Colombier 		b = i>>6;
92*9a747e4fSDavid du Colombier 		b = (b<<6)|(b<<4)|(b<<2)|b;
93*9a747e4fSDavid du Colombier 		g = (i>>3) & 7;
94*9a747e4fSDavid du Colombier 		g = (g<<5)|(g<<2)|(g>>1);
95*9a747e4fSDavid du Colombier 		r = i & 7;
96*9a747e4fSDavid du Colombier 		r = (r<<5)|(r<<2)|(r>>1);
97*9a747e4fSDavid du Colombier 		bgr8[i] = rgb2cmap(r, g, b);
98*9a747e4fSDavid du Colombier 	}
99*9a747e4fSDavid du Colombier }
100*9a747e4fSDavid du Colombier 
101*9a747e4fSDavid du Colombier static void
cvtbgr332tocmap8(uchar * dst,uchar * src,int npixel)102*9a747e4fSDavid du Colombier cvtbgr332tocmap8(uchar *dst, uchar *src, int npixel)
103*9a747e4fSDavid du Colombier {
104*9a747e4fSDavid du Colombier 	uchar *ed;
105*9a747e4fSDavid du Colombier 
106*9a747e4fSDavid du Colombier 	ed = dst+npixel;
107*9a747e4fSDavid du Colombier 	while(dst < ed)
108*9a747e4fSDavid du Colombier 		*dst++ = bgr8[*src++];
109*9a747e4fSDavid du Colombier }
110*9a747e4fSDavid du Colombier 
111*9a747e4fSDavid du Colombier void
choosecolor(Vnc * v)112*9a747e4fSDavid du Colombier choosecolor(Vnc *v)
113*9a747e4fSDavid du Colombier {
114*9a747e4fSDavid du Colombier 	int bpp, depth;
115*9a747e4fSDavid du Colombier 	ulong chan;
116*9a747e4fSDavid du Colombier 
117*9a747e4fSDavid du Colombier 	bpp = screen->depth;
118*9a747e4fSDavid du Colombier 	if((bpp / 8) * 8 != bpp)
119*9a747e4fSDavid du Colombier 		sysfatal("screen not supported");
120*9a747e4fSDavid du Colombier 
121*9a747e4fSDavid du Colombier 	depth = screen->depth;
122*9a747e4fSDavid du Colombier 	chan = screen->chan;
123*9a747e4fSDavid du Colombier 
124*9a747e4fSDavid du Colombier 	if(bpp == 24){
125*9a747e4fSDavid du Colombier 		if(verbose)
126*9a747e4fSDavid du Colombier 			fprint(2, "24bit emulation using 32bpp\n");
127*9a747e4fSDavid du Colombier 		bpp = 32;
128*9a747e4fSDavid du Colombier 		cvtpixels = cvt32to24;
129*9a747e4fSDavid du Colombier 	}
130*9a747e4fSDavid du Colombier 
131*9a747e4fSDavid du Colombier 	if(chan == CMAP8){
132*9a747e4fSDavid du Colombier 		if(bpp12){
133*9a747e4fSDavid du Colombier 			if(verbose)
134*9a747e4fSDavid du Colombier 				fprint(2, "8bit emulation using 12bpp\n");
135*9a747e4fSDavid du Colombier 			bpp = 16;
136*9a747e4fSDavid du Colombier 			depth = 12;
137*9a747e4fSDavid du Colombier 			chan = RGB12;
138*9a747e4fSDavid du Colombier 			cvtpixels = cvtrgb12tocmap8;
139*9a747e4fSDavid du Colombier 			mkrgbtab();
140*9a747e4fSDavid du Colombier 		}else{
141*9a747e4fSDavid du Colombier 			if(verbose)
142*9a747e4fSDavid du Colombier 				fprint(2, "8bit emulation using 6bpp\n");	/* 6: we throw away 1 r, g bit */
143*9a747e4fSDavid du Colombier 			bpp = 8;
144*9a747e4fSDavid du Colombier 			depth = 8;
145*9a747e4fSDavid du Colombier 			chan = BGR8;
146*9a747e4fSDavid du Colombier 			cvtpixels = cvtbgr332tocmap8;
147*9a747e4fSDavid du Colombier 			mkbgrtab();
148*9a747e4fSDavid du Colombier 		}
149*9a747e4fSDavid du Colombier 	}
150*9a747e4fSDavid du Colombier 
151*9a747e4fSDavid du Colombier 	v->bpp = bpp;
152*9a747e4fSDavid du Colombier 	v->depth = depth;
153*9a747e4fSDavid du Colombier 	v->truecolor = 1;
154*9a747e4fSDavid du Colombier 	v->bigendian = 0;
155*9a747e4fSDavid du Colombier 	chan2fmt(v, chan);
156*9a747e4fSDavid du Colombier 	if(v->red.max == 0 || v->green.max == 0 || v->blue.max == 0)
157*9a747e4fSDavid du Colombier 		sysfatal("screen not supported");
158*9a747e4fSDavid du Colombier 
159*9a747e4fSDavid du Colombier 	if(verbose)
160*9a747e4fSDavid du Colombier 		fprint(2, "%d bpp, %d depth, 0x%lx chan, %d truecolor, %d bigendian\n",
161*9a747e4fSDavid du Colombier 			v->bpp, v->depth, screen->chan, v->truecolor, v->bigendian);
162*9a747e4fSDavid du Colombier 
163*9a747e4fSDavid du Colombier 	/* send information to server */
164*9a747e4fSDavid du Colombier 	vncwrchar(v, MPixFmt);
165*9a747e4fSDavid du Colombier 	vncwrchar(v, 0);	/* padding */
166*9a747e4fSDavid du Colombier 	vncwrshort(v, 0);
167*9a747e4fSDavid du Colombier 	vncwrpixfmt(v, &v->Pixfmt);
168*9a747e4fSDavid du Colombier 	vncflush(v);
169*9a747e4fSDavid du Colombier }
170