readyuv.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 }