12 static int clamp[CLAMPOFF+256+CLAMPOFF];
16 _remaperror(char *fmt, ...)
22 vseprint(buf, buf+sizeof buf, fmt, arg);
30 torgbv(Rawimage *i, int errdiff)
32 int j, k, rgb, x, y, er, eg, eb, col, t;
33 int r, g, b, r1, g1, b1;
34 int *ered, *egrn, *eblu, *rp, *gp, *bp;
41 uchar *cmap, *cm, *in, *out, *inp, *outp, cmap1[3*256], map[256], *rpic, *bpic, *gpic;
44 errstr(err, sizeof err); /* throw it away */
45 im = malloc(sizeof(Rawimage));
48 memset(im, 0, sizeof(Rawimage));
49 im->chans[0] = malloc(i->chanlen);
50 if(im->chans[0] == nil){
57 im->chanlen = i->chanlen;
59 dx = i->r.max.x-i->r.min.x;
60 dy = i->r.max.y-i->r.min.y;
65 for(j=0; j<CLAMPOFF; j++)
68 clamp[CLAMPOFF+j] = (j>>4);
69 for(j=0; j<CLAMPOFF; j++)
70 clamp[CLAMPOFF+256+j] = (255>>4);
78 ered = malloc((dx+1)*sizeof(int));
79 egrn = malloc((dx+1)*sizeof(int));
80 eblu = malloc((dx+1)*sizeof(int));
81 if(ered==nil || egrn==nil || eblu==nil){
87 return _remaperror("remap: malloc failed: %r");
89 memset(ered, 0, (dx+1)*sizeof(int));
90 memset(egrn, 0, (dx+1)*sizeof(int));
91 memset(eblu, 0, (dx+1)*sizeof(int));
95 return _remaperror("remap: can't recognize channel type %d", i->chandesc);
98 return _remaperror("remap: image has no color map");
100 return _remaperror("remap: can't handle nchans %d", i->nchans);
102 if(i->cmaplen == 3*(1<<j))
105 return _remaperror("remap: can't do colormap size 3*%d", i->cmaplen/3);
106 if(i->cmaplen != 3*256){
107 /* to avoid a range check in inner loop below, make a full-size cmap */
108 memmove(cmap1, cmap, i->cmaplen);
113 for(j=0; j<256; j++){
118 map[j] = closestrgb[b+16*(g+16*r)];
120 for(j=0; j<i->chanlen; j++)
123 /* modified floyd steinberg, coefficients (1 0) 3/16, (0, 1) 3/16, (1, 1) 7/16 */
132 cm = &cmap[3 * *inp++];
137 /* sanity checks are new */
138 if(r >= 256+CLAMPOFF)
140 if(g >= 256+CLAMPOFF)
142 if(b >= 256+CLAMPOFF)
144 r1 = clamp[r+CLAMPOFF];
145 g1 = clamp[g+CLAMPOFF];
146 b1 = clamp[b+CLAMPOFF];
147 if(r1 >= 16 || g1 >= 16 || b1 >= 16)
150 col = closestrgb[b1+16*(g1+16*r1)];
154 r -= (rgb>>16) & 0xFF;
160 g -= (rgb>>8) & 0xFF;
181 closest = closestycbcr;
184 return _remaperror("remap: RGB image has %d channels", i->nchans);
193 return _remaperror("remap: RGB image has %d channels", i->nchans);
199 gpic = i->chans[0] + 1;
200 rpic = i->chans[0] + 2;
205 /* i->chans[0]+0 is alpha */
206 bpic = i->chans[0] + 1;
207 gpic = i->chans[0] + 2;
208 rpic = i->chans[0] + 3;
211 closest = closestrgb;
218 for(j=0; j<i->chanlen; j+=bpc){
222 *outp++ = closest[b+16*(g+16*r)];
225 /* modified floyd steinberg, coefficients (1 0) 3/16, (0, 1) 3/16, (1, 1) 7/16 */
241 * Errors can be uncorrectable if converting from YCbCr,
242 * since we can't guarantee that an extremal value of one of
243 * the components selects a color with an extremal value.
244 * If we don't, the errors accumulate without bound. This
245 * doesn't happen in RGB because the closest table can guarantee
246 * a color on the edge of the gamut, producing a zero error in
247 * that component. For the rotation YCbCr space, there may be
248 * no color that can guarantee zero error at the edge.
249 * Therefore we must clamp explicitly rather than by assuming
250 * an upper error bound of CLAMPOFF. The performance difference
251 * is miniscule anyway.
268 col = closest[b1+16*(g1+16*r1)];
272 r -= (rgb>>16) & 0xFF;
278 g -= (rgb>>8) & 0xFF;
296 /* i->chans[0] + 0 is alpha */
297 rpic = i->chans[0] + 1;
304 return _remaperror("remap: Y image has %d chans", i->nchans);
308 for(j=0; j<i->chanlen; j+=bpc){
310 *outp++ = closestrgb[r+16*(r+16*r)];
313 /* modified floyd steinberg, coefficients (1 0) 3/16, (0, 1) 3/16, (1, 1) 7/16 */
320 r1 = clamp[r+CLAMPOFF];
321 col = closestrgb[r1+16*(r1+16*r1)];
325 r -= (rgb>>16) & 0xFF;