blob: d30a68438481daa561b78cf09007e11f0b4a6c85 [file] [log] [blame]
#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;
}