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 }