aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/jpg/totruecolor.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-04-21 22:19:33 +0000
committerrsc <devnull@localhost>2004-04-21 22:19:33 +0000
commit28994509cc11ac6a5443054dfae1fedfb69039bc (patch)
tree9d5adcd11af2708db0ecc246e008c308ca0f97d4 /src/cmd/jpg/totruecolor.c
parenta01e58366c54804f15f84d6e21d13f2e4080977a (diff)
downloadplan9port-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.c163
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;
+}