Blame


1 28994509 2004-04-21 devnull #include <u.h>
2 28994509 2004-04-21 devnull #include <libc.h>
3 28994509 2004-04-21 devnull #include <bio.h>
4 28994509 2004-04-21 devnull #include <draw.h>
5 28994509 2004-04-21 devnull #include "imagefile.h"
6 28994509 2004-04-21 devnull
7 28994509 2004-04-21 devnull #include "rgbv.h"
8 28994509 2004-04-21 devnull #include "ycbcr.h"
9 28994509 2004-04-21 devnull
10 28994509 2004-04-21 devnull #define CLAMPOFF 128
11 28994509 2004-04-21 devnull
12 28994509 2004-04-21 devnull static int clamp[CLAMPOFF+256+CLAMPOFF];
13 28994509 2004-04-21 devnull static int inited;
14 28994509 2004-04-21 devnull
15 28994509 2004-04-21 devnull void*
16 28994509 2004-04-21 devnull _remaperror(char *fmt, ...)
17 28994509 2004-04-21 devnull {
18 28994509 2004-04-21 devnull va_list arg;
19 28994509 2004-04-21 devnull char buf[256];
20 28994509 2004-04-21 devnull
21 28994509 2004-04-21 devnull va_start(arg, fmt);
22 28994509 2004-04-21 devnull vseprint(buf, buf+sizeof buf, fmt, arg);
23 28994509 2004-04-21 devnull va_end(arg);
24 28994509 2004-04-21 devnull
25 28994509 2004-04-21 devnull werrstr(buf);
26 28994509 2004-04-21 devnull return nil;
27 28994509 2004-04-21 devnull }
28 28994509 2004-04-21 devnull
29 28994509 2004-04-21 devnull Rawimage*
30 28994509 2004-04-21 devnull torgbv(Rawimage *i, int errdiff)
31 28994509 2004-04-21 devnull {
32 28994509 2004-04-21 devnull int j, k, rgb, x, y, er, eg, eb, col, t;
33 28994509 2004-04-21 devnull int r, g, b, r1, g1, b1;
34 28994509 2004-04-21 devnull int *ered, *egrn, *eblu, *rp, *gp, *bp;
35 28994509 2004-04-21 devnull uint *map3;
36 28994509 2004-04-21 devnull uchar *closest;
37 28994509 2004-04-21 devnull Rawimage *im;
38 28994509 2004-04-21 devnull int dx, dy;
39 28994509 2004-04-21 devnull char err[ERRMAX];
40 28994509 2004-04-21 devnull uchar *cmap, *cm, *in, *out, *inp, *outp, cmap1[3*256], map[256], *rpic, *bpic, *gpic;
41 28994509 2004-04-21 devnull
42 28994509 2004-04-21 devnull err[0] = '\0';
43 28994509 2004-04-21 devnull errstr(err, sizeof err); /* throw it away */
44 28994509 2004-04-21 devnull im = malloc(sizeof(Rawimage));
45 28994509 2004-04-21 devnull if(im == nil)
46 28994509 2004-04-21 devnull return nil;
47 28994509 2004-04-21 devnull memset(im, 0, sizeof(Rawimage));
48 28994509 2004-04-21 devnull im->chans[0] = malloc(i->chanlen);
49 28994509 2004-04-21 devnull if(im->chans[0] == nil){
50 28994509 2004-04-21 devnull free(im);
51 28994509 2004-04-21 devnull return nil;
52 28994509 2004-04-21 devnull }
53 28994509 2004-04-21 devnull im->r = i->r;
54 28994509 2004-04-21 devnull im->nchans = 1;
55 28994509 2004-04-21 devnull im->chandesc = CRGBV;
56 28994509 2004-04-21 devnull im->chanlen = i->chanlen;
57 28994509 2004-04-21 devnull
58 28994509 2004-04-21 devnull dx = i->r.max.x-i->r.min.x;
59 28994509 2004-04-21 devnull dy = i->r.max.y-i->r.min.y;
60 28994509 2004-04-21 devnull cmap = i->cmap;
61 28994509 2004-04-21 devnull
62 28994509 2004-04-21 devnull if(inited == 0){
63 28994509 2004-04-21 devnull inited = 1;
64 28994509 2004-04-21 devnull for(j=0; j<CLAMPOFF; j++)
65 28994509 2004-04-21 devnull clamp[j] = 0;
66 28994509 2004-04-21 devnull for(j=0; j<256; j++)
67 28994509 2004-04-21 devnull clamp[CLAMPOFF+j] = (j>>4);
68 28994509 2004-04-21 devnull for(j=0; j<CLAMPOFF; j++)
69 28994509 2004-04-21 devnull clamp[CLAMPOFF+256+j] = (255>>4);
70 28994509 2004-04-21 devnull }
71 28994509 2004-04-21 devnull
72 28994509 2004-04-21 devnull in = i->chans[0];
73 28994509 2004-04-21 devnull inp = in;
74 28994509 2004-04-21 devnull out = im->chans[0];
75 28994509 2004-04-21 devnull outp = out;
76 28994509 2004-04-21 devnull
77 28994509 2004-04-21 devnull ered = malloc((dx+1)*sizeof(int));
78 28994509 2004-04-21 devnull egrn = malloc((dx+1)*sizeof(int));
79 28994509 2004-04-21 devnull eblu = malloc((dx+1)*sizeof(int));
80 28994509 2004-04-21 devnull if(ered==nil || egrn==nil || eblu==nil){
81 28994509 2004-04-21 devnull free(im->chans[0]);
82 28994509 2004-04-21 devnull free(im);
83 28994509 2004-04-21 devnull free(ered);
84 28994509 2004-04-21 devnull free(egrn);
85 28994509 2004-04-21 devnull free(eblu);
86 28994509 2004-04-21 devnull return _remaperror("remap: malloc failed: %r");
87 28994509 2004-04-21 devnull }
88 28994509 2004-04-21 devnull memset(ered, 0, (dx+1)*sizeof(int));
89 28994509 2004-04-21 devnull memset(egrn, 0, (dx+1)*sizeof(int));
90 28994509 2004-04-21 devnull memset(eblu, 0, (dx+1)*sizeof(int));
91 28994509 2004-04-21 devnull
92 28994509 2004-04-21 devnull switch(i->chandesc){
93 28994509 2004-04-21 devnull default:
94 28994509 2004-04-21 devnull return _remaperror("remap: can't recognize channel type %d", i->chandesc);
95 28994509 2004-04-21 devnull case CRGB1:
96 28994509 2004-04-21 devnull if(cmap == nil)
97 28994509 2004-04-21 devnull return _remaperror("remap: image has no color map");
98 28994509 2004-04-21 devnull if(i->nchans != 1)
99 28994509 2004-04-21 devnull return _remaperror("remap: can't handle nchans %d", i->nchans);
100 28994509 2004-04-21 devnull for(j=1; j<=8; j++)
101 28994509 2004-04-21 devnull if(i->cmaplen == 3*(1<<j))
102 28994509 2004-04-21 devnull break;
103 28994509 2004-04-21 devnull if(j > 8)
104 28994509 2004-04-21 devnull return _remaperror("remap: can't do colormap size 3*%d", i->cmaplen/3);
105 28994509 2004-04-21 devnull if(i->cmaplen != 3*256){
106 28994509 2004-04-21 devnull /* to avoid a range check in inner loop below, make a full-size cmap */
107 28994509 2004-04-21 devnull memmove(cmap1, cmap, i->cmaplen);
108 28994509 2004-04-21 devnull cmap = cmap1;
109 28994509 2004-04-21 devnull }
110 28994509 2004-04-21 devnull if(errdiff == 0){
111 28994509 2004-04-21 devnull k = 0;
112 28994509 2004-04-21 devnull for(j=0; j<256; j++){
113 28994509 2004-04-21 devnull r = cmap[k]>>4;
114 28994509 2004-04-21 devnull g = cmap[k+1]>>4;
115 28994509 2004-04-21 devnull b = cmap[k+2]>>4;
116 28994509 2004-04-21 devnull k += 3;
117 28994509 2004-04-21 devnull map[j] = closestrgb[b+16*(g+16*r)];
118 28994509 2004-04-21 devnull }
119 28994509 2004-04-21 devnull for(j=0; j<i->chanlen; j++)
120 28994509 2004-04-21 devnull out[j] = map[in[j]];
121 28994509 2004-04-21 devnull }else{
122 28994509 2004-04-21 devnull /* modified floyd steinberg, coefficients (1 0) 3/16, (0, 1) 3/16, (1, 1) 7/16 */
123 28994509 2004-04-21 devnull for(y=0; y<dy; y++){
124 28994509 2004-04-21 devnull er = 0;
125 28994509 2004-04-21 devnull eg = 0;
126 28994509 2004-04-21 devnull eb = 0;
127 28994509 2004-04-21 devnull rp = ered;
128 28994509 2004-04-21 devnull gp = egrn;
129 28994509 2004-04-21 devnull bp = eblu;
130 28994509 2004-04-21 devnull for(x=0; x<dx; x++){
131 28994509 2004-04-21 devnull cm = &cmap[3 * *inp++];
132 28994509 2004-04-21 devnull r = cm[0] +*rp;
133 28994509 2004-04-21 devnull g = cm[1] +*gp;
134 28994509 2004-04-21 devnull b = cm[2] +*bp;
135 28994509 2004-04-21 devnull
136 28994509 2004-04-21 devnull /* sanity checks are new */
137 28994509 2004-04-21 devnull if(r >= 256+CLAMPOFF)
138 28994509 2004-04-21 devnull r = 0;
139 28994509 2004-04-21 devnull if(g >= 256+CLAMPOFF)
140 28994509 2004-04-21 devnull g = 0;
141 28994509 2004-04-21 devnull if(b >= 256+CLAMPOFF)
142 28994509 2004-04-21 devnull b = 0;
143 28994509 2004-04-21 devnull r1 = clamp[r+CLAMPOFF];
144 28994509 2004-04-21 devnull g1 = clamp[g+CLAMPOFF];
145 28994509 2004-04-21 devnull b1 = clamp[b+CLAMPOFF];
146 28994509 2004-04-21 devnull if(r1 >= 16 || g1 >= 16 || b1 >= 16)
147 28994509 2004-04-21 devnull col = 0;
148 28994509 2004-04-21 devnull else
149 28994509 2004-04-21 devnull col = closestrgb[b1+16*(g1+16*r1)];
150 28994509 2004-04-21 devnull *outp++ = col;
151 28994509 2004-04-21 devnull
152 28994509 2004-04-21 devnull rgb = rgbmap[col];
153 28994509 2004-04-21 devnull r -= (rgb>>16) & 0xFF;
154 28994509 2004-04-21 devnull t = (3*r)>>4;
155 28994509 2004-04-21 devnull *rp++ = t+er;
156 28994509 2004-04-21 devnull *rp += t;
157 28994509 2004-04-21 devnull er = r-3*t;
158 28994509 2004-04-21 devnull
159 28994509 2004-04-21 devnull g -= (rgb>>8) & 0xFF;
160 28994509 2004-04-21 devnull t = (3*g)>>4;
161 28994509 2004-04-21 devnull *gp++ = t+eg;
162 28994509 2004-04-21 devnull *gp += t;
163 28994509 2004-04-21 devnull eg = g-3*t;
164 28994509 2004-04-21 devnull
165 28994509 2004-04-21 devnull b -= rgb & 0xFF;
166 28994509 2004-04-21 devnull t = (3*b)>>4;
167 28994509 2004-04-21 devnull *bp++ = t+eb;
168 28994509 2004-04-21 devnull *bp += t;
169 28994509 2004-04-21 devnull eb = b-3*t;
170 28994509 2004-04-21 devnull }
171 28994509 2004-04-21 devnull }
172 28994509 2004-04-21 devnull }
173 28994509 2004-04-21 devnull break;
174 28994509 2004-04-21 devnull
175 28994509 2004-04-21 devnull case CYCbCr:
176 28994509 2004-04-21 devnull closest = closestycbcr;
177 28994509 2004-04-21 devnull map3 = ycbcrmap;
178 28994509 2004-04-21 devnull goto Threecolor;
179 28994509 2004-04-21 devnull
180 28994509 2004-04-21 devnull case CRGB:
181 28994509 2004-04-21 devnull closest = closestrgb;
182 28994509 2004-04-21 devnull map3 = rgbmap;
183 28994509 2004-04-21 devnull
184 28994509 2004-04-21 devnull Threecolor:
185 28994509 2004-04-21 devnull if(i->nchans != 3)
186 28994509 2004-04-21 devnull return _remaperror("remap: RGB image has %d channels", i->nchans);
187 28994509 2004-04-21 devnull rpic = i->chans[0];
188 28994509 2004-04-21 devnull gpic = i->chans[1];
189 28994509 2004-04-21 devnull bpic = i->chans[2];
190 28994509 2004-04-21 devnull if(errdiff == 0){
191 28994509 2004-04-21 devnull for(j=0; j<i->chanlen; j++){
192 28994509 2004-04-21 devnull r = rpic[j]>>4;
193 28994509 2004-04-21 devnull g = gpic[j]>>4;
194 28994509 2004-04-21 devnull b = bpic[j]>>4;
195 28994509 2004-04-21 devnull out[j] = closest[b+16*(g+16*r)];
196 28994509 2004-04-21 devnull }
197 28994509 2004-04-21 devnull }else{
198 28994509 2004-04-21 devnull /* modified floyd steinberg, coefficients (1 0) 3/16, (0, 1) 3/16, (1, 1) 7/16 */
199 28994509 2004-04-21 devnull for(y=0; y<dy; y++){
200 28994509 2004-04-21 devnull er = 0;
201 28994509 2004-04-21 devnull eg = 0;
202 28994509 2004-04-21 devnull eb = 0;
203 28994509 2004-04-21 devnull rp = ered;
204 28994509 2004-04-21 devnull gp = egrn;
205 28994509 2004-04-21 devnull bp = eblu;
206 28994509 2004-04-21 devnull for(x=0; x<dx; x++){
207 28994509 2004-04-21 devnull r = *rpic++ + *rp;
208 28994509 2004-04-21 devnull g = *gpic++ + *gp;
209 28994509 2004-04-21 devnull b = *bpic++ + *bp;
210 28994509 2004-04-21 devnull /*
211 28994509 2004-04-21 devnull * Errors can be uncorrectable if converting from YCbCr,
212 28994509 2004-04-21 devnull * since we can't guarantee that an extremal value of one of
213 28994509 2004-04-21 devnull * the components selects a color with an extremal value.
214 28994509 2004-04-21 devnull * If we don't, the errors accumulate without bound. This
215 28994509 2004-04-21 devnull * doesn't happen in RGB because the closest table can guarantee
216 28994509 2004-04-21 devnull * a color on the edge of the gamut, producing a zero error in
217 28994509 2004-04-21 devnull * that component. For the rotation YCbCr space, there may be
218 28994509 2004-04-21 devnull * no color that can guarantee zero error at the edge.
219 28994509 2004-04-21 devnull * Therefore we must clamp explicitly rather than by assuming
220 28994509 2004-04-21 devnull * an upper error bound of CLAMPOFF. The performance difference
221 28994509 2004-04-21 devnull * is miniscule anyway.
222 28994509 2004-04-21 devnull */
223 28994509 2004-04-21 devnull if(r < 0)
224 28994509 2004-04-21 devnull r = 0;
225 28994509 2004-04-21 devnull else if(r > 255)
226 28994509 2004-04-21 devnull r = 255;
227 28994509 2004-04-21 devnull if(g < 0)
228 28994509 2004-04-21 devnull g = 0;
229 28994509 2004-04-21 devnull else if(g > 255)
230 28994509 2004-04-21 devnull g = 255;
231 28994509 2004-04-21 devnull if(b < 0)
232 28994509 2004-04-21 devnull b = 0;
233 28994509 2004-04-21 devnull else if(b > 255)
234 28994509 2004-04-21 devnull b = 255;
235 28994509 2004-04-21 devnull r1 = r>>4;
236 28994509 2004-04-21 devnull g1 = g>>4;
237 28994509 2004-04-21 devnull b1 = b>>4;
238 28994509 2004-04-21 devnull col = closest[b1+16*(g1+16*r1)];
239 28994509 2004-04-21 devnull *outp++ = col;
240 28994509 2004-04-21 devnull
241 28994509 2004-04-21 devnull rgb = map3[col];
242 28994509 2004-04-21 devnull r -= (rgb>>16) & 0xFF;
243 28994509 2004-04-21 devnull t = (3*r)>>4;
244 28994509 2004-04-21 devnull *rp++ = t+er;
245 28994509 2004-04-21 devnull *rp += t;
246 28994509 2004-04-21 devnull er = r-3*t;
247 28994509 2004-04-21 devnull
248 28994509 2004-04-21 devnull g -= (rgb>>8) & 0xFF;
249 28994509 2004-04-21 devnull t = (3*g)>>4;
250 28994509 2004-04-21 devnull *gp++ = t+eg;
251 28994509 2004-04-21 devnull *gp += t;
252 28994509 2004-04-21 devnull eg = g-3*t;
253 28994509 2004-04-21 devnull
254 28994509 2004-04-21 devnull b -= rgb & 0xFF;
255 28994509 2004-04-21 devnull t = (3*b)>>4;
256 28994509 2004-04-21 devnull *bp++ = t+eb;
257 28994509 2004-04-21 devnull *bp += t;
258 28994509 2004-04-21 devnull eb = b-3*t;
259 28994509 2004-04-21 devnull }
260 28994509 2004-04-21 devnull }
261 28994509 2004-04-21 devnull }
262 28994509 2004-04-21 devnull break;
263 28994509 2004-04-21 devnull
264 28994509 2004-04-21 devnull case CY:
265 28994509 2004-04-21 devnull if(i->nchans != 1)
266 28994509 2004-04-21 devnull return _remaperror("remap: Y image has %d chans", i->nchans);
267 28994509 2004-04-21 devnull rpic = i->chans[0];
268 28994509 2004-04-21 devnull if(errdiff == 0){
269 28994509 2004-04-21 devnull for(j=0; j<i->chanlen; j++){
270 28994509 2004-04-21 devnull r = rpic[j]>>4;
271 28994509 2004-04-21 devnull *outp++ = closestrgb[r+16*(r+16*r)];
272 28994509 2004-04-21 devnull }
273 28994509 2004-04-21 devnull }else{
274 28994509 2004-04-21 devnull /* modified floyd steinberg, coefficients (1 0) 3/16, (0, 1) 3/16, (1, 1) 7/16 */
275 28994509 2004-04-21 devnull for(y=0; y<dy; y++){
276 28994509 2004-04-21 devnull er = 0;
277 28994509 2004-04-21 devnull rp = ered;
278 28994509 2004-04-21 devnull for(x=0; x<dx; x++){
279 28994509 2004-04-21 devnull r = *inp++ + *rp;
280 28994509 2004-04-21 devnull r1 = clamp[r+CLAMPOFF];
281 28994509 2004-04-21 devnull col = closestrgb[r1+16*(r1+16*r1)];
282 28994509 2004-04-21 devnull *outp++ = col;
283 28994509 2004-04-21 devnull
284 28994509 2004-04-21 devnull rgb = rgbmap[col];
285 28994509 2004-04-21 devnull r -= (rgb>>16) & 0xFF;
286 28994509 2004-04-21 devnull t = (3*r)>>4;
287 28994509 2004-04-21 devnull *rp++ = t+er;
288 28994509 2004-04-21 devnull *rp += t;
289 28994509 2004-04-21 devnull er = r-3*t;
290 28994509 2004-04-21 devnull }
291 28994509 2004-04-21 devnull }
292 28994509 2004-04-21 devnull }
293 28994509 2004-04-21 devnull break;
294 28994509 2004-04-21 devnull }
295 28994509 2004-04-21 devnull free(ered);
296 28994509 2004-04-21 devnull free(egrn);
297 28994509 2004-04-21 devnull free(eblu);
298 28994509 2004-04-21 devnull return im;
299 28994509 2004-04-21 devnull }