Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <draw.h>
5 #include "imagefile.h"
7 enum {
8 c1 = 2871, /* 1.402 * 2048 */
9 c2 = 705, /* 0.34414 * 2048 */
10 c3 = 1463, /* 0.71414 * 2048 */
11 c4 = 3629, /* 1.772 * 2048 */
12 };
14 Rawimage*
15 totruecolor(Rawimage *i, int chandesc)
16 {
17 int j, k;
18 Rawimage *im;
19 char err[ERRMAX];
20 uchar *rp, *gp, *bp, *cmap, *inp, *outp, cmap1[3*256];
21 int r, g, b, Y, Cr, Cb;
23 if(chandesc!=CY && chandesc!=CRGB24)
24 return _remaperror("remap: can't convert to chandesc %d", chandesc);
26 err[0] = '\0';
27 errstr(err, sizeof err); /* throw it away */
28 im = malloc(sizeof(Rawimage));
29 if(im == nil)
30 return nil;
31 memset(im, 0, sizeof(Rawimage));
32 if(chandesc == CY)
33 im->chanlen = i->chanlen;
34 else
35 im->chanlen = 3*i->chanlen;
36 im->chandesc = chandesc;
37 im->chans[0] = malloc(im->chanlen);
38 if(im->chans[0] == nil){
39 free(im);
40 return nil;
41 }
42 im->r = i->r;
43 im->nchans = 1;
45 cmap = i->cmap;
47 outp = im->chans[0];
49 switch(i->chandesc){
50 default:
51 return _remaperror("remap: can't recognize channel type %d", i->chandesc);
52 case CY:
53 if(i->nchans != 1)
54 return _remaperror("remap: Y image has %d chans", i->nchans);
55 if(chandesc == CY){
56 memmove(im->chans[0], i->chans[0], i->chanlen);
57 break;
58 }
59 /* convert to three color */
60 inp = i->chans[0];
61 for(j=0; j<i->chanlen; j++){
62 k = *inp++;
63 *outp++ = k;
64 *outp++ = k;
65 *outp++ = k;
66 }
67 break;
69 case CRGB1:
70 if(cmap == nil)
71 return _remaperror("remap: image has no color map");
72 if(i->nchans != 1)
73 return _remaperror("remap: can't handle nchans %d", i->nchans);
74 for(j=1; j<=8; j++)
75 if(i->cmaplen == 3*(1<<j))
76 break;
77 if(j > 8)
78 return _remaperror("remap: can't do colormap size 3*%d", i->cmaplen/3);
79 if(i->cmaplen != 3*256){
80 /* to avoid a range check in loop below, make a full-size cmap */
81 memmove(cmap1, cmap, i->cmaplen);
82 cmap = cmap1;
83 }
84 inp = i->chans[0];
85 if(chandesc == CY){
86 for(j=0; j<i->chanlen; j++){
87 k = *inp++;
88 r = cmap[3*k+2];
89 g = cmap[3*k+1];
90 b = cmap[3*k+0];
91 r = (2125*r + 7154*g + 721*b)/10000; /* Poynton page 84 */
92 *outp++ = r;
93 }
94 }else{
95 for(j=0; j<i->chanlen; j++){
96 k = *inp++;
97 *outp++ = cmap[3*k+2];
98 *outp++ = cmap[3*k+1];
99 *outp++ = cmap[3*k+0];
102 break;
104 case CRGB:
105 if(i->nchans != 3)
106 return _remaperror("remap: can't handle nchans %d", i->nchans);
107 rp = i->chans[0];
108 gp = i->chans[1];
109 bp = i->chans[2];
110 if(chandesc == CY){
111 for(j=0; j<i->chanlen; j++){
112 r = *bp++;
113 g = *gp++;
114 b = *rp++;
115 r = (2125*r + 7154*g + 721*b)/10000; /* Poynton page 84 */
116 *outp++ = r;
118 }else
119 for(j=0; j<i->chanlen; j++){
120 *outp++ = *bp++;
121 *outp++ = *gp++;
122 *outp++ = *rp++;
124 break;
126 case CYCbCr:
127 if(i->nchans != 3)
128 return _remaperror("remap: can't handle nchans %d", i->nchans);
129 rp = i->chans[0];
130 gp = i->chans[1];
131 bp = i->chans[2];
132 for(j=0; j<i->chanlen; j++){
133 Y = *rp++ << 11;
134 Cb = *gp++ - 128;
135 Cr = *bp++ - 128;
136 r = (Y+c1*Cr) >> 11;
137 g = (Y-c2*Cb-c3*Cr) >> 11;
138 b = (Y+c4*Cb) >> 11;
139 if(r < 0)
140 r = 0;
141 if(r > 255)
142 r = 255;
143 if(g < 0)
144 g = 0;
145 if(g > 255)
146 g = 255;
147 if(b < 0)
148 b = 0;
149 if(b > 255)
150 b = 255;
151 if(chandesc == CY){
152 r = (2125*r + 7154*g + 721*b)/10000;
153 *outp++ = r;
154 }else{
155 *outp++ = b;
156 *outp++ = g;
157 *outp++ = r;
160 break;
162 return im;