Blob


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"
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 */
26 enum {
27 PAL = 576, NTSC = 486 };
30 static int lsbtab[] = { 6, 4, 2, 0};
32 static int
33 clip(int x)
34 {
35 x >>= 18;
37 if (x > 255)
38 return 0xff;
39 if (x <= 0)
40 return 0;
41 return x;
42 }
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;
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 }
62 if ((a = calloc(sizeof(Rawimage), 1)) == nil)
63 sysfatal("no memory");
65 if ((array = calloc(sizeof(Rawimage * ), 2)) == nil)
66 sysfatal("no memory");
67 array[0] = a;
68 array[1] = nil;
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 }
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 }
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);
107 e = "no memory";
108 if ((frm = malloc(720 * 2 * lines * sizeof(ushort))) == nil)
109 goto Error;
111 for (c = 0; c < 3; c++)
112 if ((a->chans[c] = malloc(720 * lines)) == nil)
113 goto Error;
115 e = "read file";
116 for (l = 0; l < lines; l++) {
117 if (Bread(bp, buf, 720 * 2) == -1)
118 goto Error;
120 base = l * 720 * 2;
121 for (w = 0; w < 720 * 2; w++)
122 frm[base + w] = ((ushort)buf[w]) << 2;
126 if (bits == 10)
127 for (l = 0; l < lines; l++) {
128 if (Bread(bp, buf, 720 / 2) == -1)
129 goto Error;
132 base = l * 720 * 2;
133 for (w = 0; w < 720 * 2; w++)
134 frm[base + w] |= buf[w / 4] >> lsbtab[w % 4];
137 mux = frm;
138 end = frm + 720 * lines * 2;
139 r = a->chans[0];
140 g = a->chans[1];
141 b = a->chans[2];
143 while (mux < end) {
144 cb = *mux++ - 512;
145 y1 = (*mux++ - 64) * 76310;
146 cr = *mux++ - 512;
147 y2 = (*mux++ - 64) * 76310;
149 *r++ = clip((104635 * cr) + y1);
150 *g++ = clip((-25690 * cb + -53294 * cr) + y1);
151 *b++ = clip((132278 * cb) + y1);
153 *r++ = clip((104635 * cr) + y2);
154 *g++ = clip((-25690 * cb + -53294 * cr) + y2);
155 *b++ = clip((132278 * cb) + y2);
157 free(frm);
158 return array;
160 Error:
162 errstr(ebuf, sizeof ebuf);
163 if (ebuf[0] == 0)
164 strcpy(ebuf, e);
165 errstr(ebuf, sizeof ebuf);
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;
177 Rawimage**
178 readyuv(int fd, int colorspace)
180 Rawimage * *a;
181 Biobuf b;
183 if (Binit(&b, fd, OREAD) < 0)
184 return nil;
185 a = Breadyuv(&b, colorspace);
186 Bterm(&b);
187 return a;