plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

totruecolor.c (3406B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <bio.h>
      4 #include <draw.h>
      5 #include "imagefile.h"
      6 
      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 };
     13 
     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;
     22 
     23 	if(chandesc!=CY && chandesc!=CRGB24)
     24 		return _remaperror("remap: can't convert to chandesc %d", chandesc);
     25 
     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;
     44 
     45 	cmap = i->cmap;
     46 
     47 	outp = im->chans[0];
     48 
     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;
     68 
     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];
    100 			}
    101 		}
    102 		break;
    103 
    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;
    117 			}
    118 		}else
    119 			for(j=0; j<i->chanlen; j++){
    120 				*outp++ = *bp++;
    121 				*outp++ = *gp++;
    122 				*outp++ = *rp++;
    123 			}
    124 		break;
    125 
    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;
    158 			}
    159 		}
    160 		break;
    161 	}
    162 	return im;
    163 }