123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <draw.h>
- #include "imagefile.h"
- enum {
- c1 = 2871, /* 1.402 * 2048 */
- c2 = 705, /* 0.34414 * 2048 */
- c3 = 1463, /* 0.71414 * 2048 */
- c4 = 3629, /* 1.772 * 2048 */
- };
- Rawimage*
- totruecolor(Rawimage *i, int chandesc)
- {
- int j, k;
- Rawimage *im;
- char err[ERRMAX];
- uchar *rp, *gp, *bp, *cmap, *inp, *outp, cmap1[3*256];
- int r, g, b, Y, Cr, Cb;
- if(chandesc!=CY && chandesc!=CRGB24)
- return _remaperror("remap: can't convert to chandesc %d", chandesc);
- err[0] = '\0';
- errstr(err, sizeof err); /* throw it away */
- im = malloc(sizeof(Rawimage));
- if(im == nil)
- return nil;
- memset(im, 0, sizeof(Rawimage));
- if(chandesc == CY)
- im->chanlen = i->chanlen;
- else
- im->chanlen = 3*i->chanlen;
- im->chandesc = chandesc;
- im->chans[0] = malloc(im->chanlen);
- if(im->chans[0] == nil){
- free(im);
- return nil;
- }
- im->r = i->r;
- im->nchans = 1;
- cmap = i->cmap;
- outp = im->chans[0];
- switch(i->chandesc){
- default:
- return _remaperror("remap: can't recognize channel type %d", i->chandesc);
- case CY:
- if(i->nchans != 1)
- return _remaperror("remap: Y image has %d chans", i->nchans);
- if(chandesc == CY){
- memmove(im->chans[0], i->chans[0], i->chanlen);
- break;
- }
- /* convert to three color */
- inp = i->chans[0];
- for(j=0; j<i->chanlen; j++){
- k = *inp++;
- *outp++ = k;
- *outp++ = k;
- *outp++ = k;
- }
- break;
- case CRGB1:
- if(cmap == nil)
- return _remaperror("remap: image has no color map");
- if(i->nchans != 1)
- return _remaperror("remap: can't handle nchans %d", i->nchans);
- for(j=1; j<=8; j++)
- if(i->cmaplen == 3*(1<<j))
- break;
- if(j > 8)
- return _remaperror("remap: can't do colormap size 3*%d", i->cmaplen/3);
- if(i->cmaplen != 3*256){
- /* to avoid a range check in loop below, make a full-size cmap */
- memmove(cmap1, cmap, i->cmaplen);
- cmap = cmap1;
- }
- inp = i->chans[0];
- if(chandesc == CY){
- for(j=0; j<i->chanlen; j++){
- k = *inp++;
- r = cmap[3*k+2];
- g = cmap[3*k+1];
- b = cmap[3*k+0];
- r = (2125*r + 7154*g + 721*b)/10000; /* Poynton page 84 */
- *outp++ = r;
- }
- }else{
- for(j=0; j<i->chanlen; j++){
- k = *inp++;
- *outp++ = cmap[3*k+2];
- *outp++ = cmap[3*k+1];
- *outp++ = cmap[3*k+0];
- }
- }
- break;
- case CRGB:
- if(i->nchans != 3)
- return _remaperror("remap: can't handle nchans %d", i->nchans);
- rp = i->chans[0];
- gp = i->chans[1];
- bp = i->chans[2];
- if(chandesc == CY){
- for(j=0; j<i->chanlen; j++){
- r = *bp++;
- g = *gp++;
- b = *rp++;
- r = (2125*r + 7154*g + 721*b)/10000; /* Poynton page 84 */
- *outp++ = r;
- }
- }else
- for(j=0; j<i->chanlen; j++){
- *outp++ = *bp++;
- *outp++ = *gp++;
- *outp++ = *rp++;
- }
- break;
- case CYCbCr:
- if(i->nchans != 3)
- return _remaperror("remap: can't handle nchans %d", i->nchans);
- rp = i->chans[0];
- gp = i->chans[1];
- bp = i->chans[2];
- for(j=0; j<i->chanlen; j++){
- Y = *rp++ << 11;
- Cb = *gp++ - 128;
- Cr = *bp++ - 128;
- r = (Y+c1*Cr) >> 11;
- g = (Y-c2*Cb-c3*Cr) >> 11;
- b = (Y+c4*Cb) >> 11;
- if(r < 0)
- r = 0;
- if(r > 255)
- r = 255;
- if(g < 0)
- g = 0;
- if(g > 255)
- g = 255;
- if(b < 0)
- b = 0;
- if(b > 255)
- b = 255;
- if(chandesc == CY){
- r = (2125*r + 7154*g + 721*b)/10000;
- *outp++ = r;
- }else{
- *outp++ = b;
- *outp++ = g;
- *outp++ = r;
- }
- }
- break;
- }
- return im;
- }
|