URI:
       ttotruecolor.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       ttotruecolor.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 }