URI:
       treadyuv.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
       ---
       treadyuv.c (3517B)
       ---
            1 /* readyuv.c - read an Abekas A66 style image file.   Steve Simon, 2003 */
            2 #include <u.h>
            3 #include <libc.h>
            4 #include <bio.h>
            5 #include <draw.h>
            6 #include <ctype.h>
            7 #include "imagefile.h"
            8 
            9 /*
           10  * ITU/CCIR Rec601 states:
           11  *
           12  * R = y + 1.402 * Cr
           13  * B = Y + 1.77305 * Cb
           14  * G = Y - 0.72414 * Cr - 0.34414 * Cb
           15  *
           16  *        using 8 bit traffic
           17  * Y = 16 + 219 * Y
           18  * Cr = 128 + 224 * Cr
           19  * Cb = 128 + 224 * Cb
           20  *         or, if 10bit is used
           21  * Y = 64 + 876 * Y
           22  * Cr = 512 + 896 * Cr
           23  * Cb = 512 + 896 * Cb
           24  */
           25 
           26 enum {
           27         PAL = 576, NTSC = 486 };
           28 
           29 
           30 static int lsbtab[] = { 6, 4, 2, 0};
           31 
           32 static int
           33 clip(int x)
           34 {
           35         x >>= 18;
           36 
           37         if (x > 255)
           38                 return 0xff;
           39         if (x <= 0)
           40                 return 0;
           41         return x;
           42 }
           43 
           44 
           45 Rawimage**
           46 Breadyuv(Biobuf *bp, int colourspace)
           47 {
           48         Dir * d;
           49         Rawimage * a, **array;
           50         char        *e, ebuf[128];
           51         ushort * mux, *end, *frm;
           52         uchar buf[720 * 2], *r, *g, *b;
           53         int        y1, y2, cb, cr, sz, c, l, w, base, bits, lines;
           54 
           55         frm = 0;
           56         if (colourspace != CYCbCr) {
           57                 errstr(ebuf, sizeof ebuf);        /* throw it away */
           58                 werrstr("ReadYUV: unknown colour space %d", colourspace);
           59                 return nil;
           60         }
           61 
           62         if ((a = calloc(sizeof(Rawimage), 1)) == nil)
           63                 sysfatal("no memory");
           64 
           65         if ((array = calloc(sizeof(Rawimage * ), 2)) == nil)
           66                 sysfatal("no memory");
           67         array[0] = a;
           68         array[1] = nil;
           69 
           70         if ((d = dirfstat(Bfildes(bp))) != nil) {
           71                 sz = d->length;
           72                 free(d);
           73         } else {
           74                 fprint(2, "cannot stat input, assuming 720x576x10bit\n");
           75                 sz = 720 * PAL * 2L + (720 * PAL / 2L);
           76         }
           77 
           78         switch (sz) {
           79         case 720 * PAL * 2:                                /* 625 x 8bit */
           80                 bits = 8;
           81                 lines = PAL;
           82                 break;
           83         case 720 * NTSC * 2:                                /* 525 x 8bit */
           84                 bits = 8;
           85                 lines = NTSC;
           86                 break;
           87         case 720 * PAL * 2 + (720 * PAL / 2) :                /* 625 x 10bit */
           88                         bits = 10;
           89                 lines = PAL;
           90                 break;
           91         case 720 * NTSC * 2 + (720 * NTSC / 2) :        /* 525 x 10bit */
           92                         bits = 10;
           93                 lines = NTSC;
           94                 break;
           95         default:
           96                 e = "unknown file size";
           97                 goto Error;
           98         }
           99 
          100         /*        print("bits=%d pixels=%d lines=%d\n", bits, 720, lines); */
          101         /* */
          102         a->nchans = 3;
          103         a->chandesc = CRGB;
          104         a->chanlen = 720 * lines;
          105         a->r = Rect(0, 0, 720, lines);
          106 
          107         e = "no memory";
          108         if ((frm = malloc(720 * 2 * lines * sizeof(ushort))) == nil)
          109                 goto Error;
          110 
          111         for (c = 0; c  < 3; c++)
          112                 if ((a->chans[c] = malloc(720 * lines)) == nil)
          113                         goto Error;
          114 
          115         e = "read file";
          116         for (l = 0; l < lines; l++) {
          117                 if (Bread(bp, buf, 720 * 2) == -1)
          118                         goto Error;
          119 
          120                 base = l * 720 * 2;
          121                 for (w = 0; w < 720 * 2; w++)
          122                         frm[base + w] = ((ushort)buf[w]) << 2;
          123         }
          124 
          125 
          126         if (bits == 10)
          127                 for (l = 0; l < lines; l++) {
          128                         if (Bread(bp, buf, 720 / 2) == -1)
          129                                 goto Error;
          130 
          131 
          132                         base = l * 720 * 2;
          133                         for (w = 0; w < 720 * 2; w++)
          134                                 frm[base + w] |= buf[w / 4] >> lsbtab[w % 4];
          135                 }
          136 
          137         mux = frm;
          138         end = frm + 720 * lines * 2;
          139         r = a->chans[0];
          140         g = a->chans[1];
          141         b = a->chans[2];
          142 
          143         while (mux < end) {
          144                 cb = *mux++ - 512;
          145                 y1 = (*mux++ - 64) * 76310;
          146                 cr = *mux++ - 512;
          147                 y2 = (*mux++ - 64) * 76310;
          148 
          149                 *r++ = clip((104635 * cr) + y1);
          150                 *g++ = clip((-25690 * cb + -53294 * cr) + y1);
          151                 *b++ = clip((132278 * cb) + y1);
          152 
          153                 *r++ = clip((104635 * cr) + y2);
          154                 *g++ = clip((-25690 * cb + -53294 * cr) + y2);
          155                 *b++ = clip((132278 * cb) + y2);
          156         }
          157         free(frm);
          158         return array;
          159 
          160 Error:
          161 
          162         errstr(ebuf, sizeof ebuf);
          163         if (ebuf[0] == 0)
          164                 strcpy(ebuf, e);
          165         errstr(ebuf, sizeof ebuf);
          166 
          167         for (c = 0; c < 3; c++)
          168                 free(a->chans[c]);
          169         free(a->cmap);
          170         free(array[0]);
          171         free(array);
          172         free(frm);
          173         return nil;
          174 }
          175 
          176 
          177 Rawimage**
          178 readyuv(int fd, int colorspace)
          179 {
          180         Rawimage * *a;
          181         Biobuf b;
          182 
          183         if (Binit(&b, fd, OREAD) < 0)
          184                 return nil;
          185         a = Breadyuv(&b, colorspace);
          186         Bterm(&b);
          187         return a;
          188 }