diff options
author | rsc <devnull@localhost> | 2004-04-21 22:19:33 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-04-21 22:19:33 +0000 |
commit | 28994509cc11ac6a5443054dfae1fedfb69039bc (patch) | |
tree | 9d5adcd11af2708db0ecc246e008c308ca0f97d4 /src/cmd/jpg/totruecolor.c | |
parent | a01e58366c54804f15f84d6e21d13f2e4080977a (diff) | |
download | plan9port-28994509cc11ac6a5443054dfae1fedfb69039bc.tar.gz plan9port-28994509cc11ac6a5443054dfae1fedfb69039bc.tar.bz2 plan9port-28994509cc11ac6a5443054dfae1fedfb69039bc.zip |
Why not?
Diffstat (limited to 'src/cmd/jpg/totruecolor.c')
-rw-r--r-- | src/cmd/jpg/totruecolor.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/cmd/jpg/totruecolor.c b/src/cmd/jpg/totruecolor.c new file mode 100644 index 00000000..0da5d9a3 --- /dev/null +++ b/src/cmd/jpg/totruecolor.c @@ -0,0 +1,163 @@ +#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; +} |