]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/jpg/readyuv.c
cwfs: back to previous version
[plan9front.git] / sys / src / cmd / jpg / readyuv.c
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 enum {
11         Pixels = 720,
12         R601pal = 576,
13         R601ntsc = 486,
14         Shift = 13
15 };
16
17
18 static int lsbtab[] = { 6, 4, 2, 0};
19
20 static int
21 looksize(char *file, vlong size, int *pixels, int *lines, int *bits)
22 {
23         Biobuf *bp;
24         uvlong l, p;
25         char *s, *a[12];
26
27         /*
28          * This may not always work, there could be an alias between file
29          * sizes of different standards stored in 8bits and 10 bits.
30          */
31         if ((bp = Bopen(file, OREAD)) == nil)
32                 return -1;
33         while((s = Brdstr(bp, '\n', 1)) != nil){
34                 if (tokenize(s, a, nelem(a)) < 3)
35                         continue;
36                 if (a[0][0] == '#')
37                         continue;
38                 p = atoll(a[3]);
39                 l = atoll(a[5]);
40                 l += atoll(a[7]);
41                 if (l*p*2 == size){
42                         *pixels = p;
43                         *lines = l;
44                         *bits = 8;
45                         break;
46                 }
47                 if ((l*p*20)/8 == size){
48                         *pixels = p;
49                         *lines = l;
50                         *bits = 10;
51                         break;
52                 }
53         }
54         Bterm(bp);
55         if (s == nil)
56                 return -1;
57         return 0;
58 }
59
60
61 static int 
62 clip(int x)
63 {
64         x >>= (Shift+2); // +2 as we assume all input images are 10 bit
65
66         if (x > 255)
67                 return 0xff;
68         if (x <= 0)
69                 return 0;
70         return x;
71 }
72
73 Rawimage**
74 Breadyuv(Biobuf *bp, int colourspace)
75 {
76         Dir *d;
77         uvlong sz;
78         Rawimage *a, **array;
79         ushort * mux, *end, *frm;
80         uchar *buf, *r, *g, *b;
81         int y1, y2, cb, cr, c, l, w, base;
82         int bits, lines, pixels;
83         int F1, F2, F3, F4;
84
85         if ((d = dirfstat(Bfildes(bp))) != nil){
86                 sz = d->length;
87                 free(d);
88         }
89         else{
90                 fprint(2, "cannot stat input, assuming pixelsx576x10bit\n");
91                 sz = Pixels * R601pal * 2L + (Pixels * R601pal / 2L);
92         }
93
94         if (looksize("/lib/video.specs", sz, &pixels, &lines, &bits) == -1){
95                 werrstr("file size not listed in /lib/video.specs");
96                 return nil;
97         }
98
99         buf = nil;
100         if (colourspace != CYCbCr) {
101                 werrstr("ReadYUV: unknown colour space %d", colourspace);
102                 return nil;
103         }
104
105         if ((a = calloc(sizeof(Rawimage), 1)) == nil)
106                 sysfatal("no memory");
107
108         if ((array = calloc(sizeof(Rawimage * ), 2)) == nil)
109                 sysfatal("no memory");
110         array[0] = a;
111         array[1] = nil;
112
113         a->nchans = 3;
114         a->chandesc = CRGB;
115         a->chanlen = pixels * lines;
116         a->r = Rect(0, 0, pixels, lines);
117
118         if ((frm = malloc(pixels*2*lines*sizeof(ushort))) == nil)
119                 goto Error;
120
121         for (c = 0; c  < 3; c++)
122                 if ((a->chans[c] = malloc(pixels*lines)) == nil)
123                         goto Error;
124
125         if ((buf = malloc(pixels*2)) == nil)
126                 goto Error;
127
128         for (l = 0; l < lines; l++) {
129                 if (Bread(bp, buf, pixels *2) == -1)
130                         goto Error;
131
132                 base = l*pixels*2;
133                 for (w = 0; w < pixels *2; w++)
134                         frm[base + w] = ((ushort)buf[w]) << 2;
135         }
136
137
138         if (bits == 10)
139                 for (l = 0; l < lines; l++) {
140                         if (Bread(bp, buf, pixels / 2) == -1)
141                                 goto Error;
142
143
144                         base = l * pixels * 2;
145                         for (w = 0; w < pixels * 2; w++)
146                                 frm[base + w] |= (buf[w / 4] >> lsbtab[w % 4]) & 3;
147                 }
148
149         mux = frm;
150         end = frm + pixels * lines * 2;
151         r = a->chans[0];
152         g = a->chans[1];
153         b = a->chans[2];
154
155         if(pixels == Pixels && lines != R601pal){       // 625
156                 F1 = floor(1.402 * (1 << Shift));
157                 F2 = floor(0.34414 * (1 << Shift));
158                 F3 = floor(0.71414 * (1 << Shift));
159                 F4 = floor(1.772 * (1 << Shift));
160         }
161         else{                           // 525
162                 F1 = floor(1.5748 * (1 << Shift));
163                 F2 = floor(0.1874 * (1 << Shift));
164                 F3 = floor(0.4681 * (1 << Shift));
165                 F4 = floor(1.8560 * (1 << Shift));
166         }
167
168         /*
169          * Fixme: fixed colourspace conversion at present
170          */
171         while (mux < end) {
172
173                 cb = *mux++ - 512;
174                 y1 = (int)*mux++ << Shift;
175                 cr = *mux++ - 512;
176                 y2 = (int)*mux++ << Shift;
177
178                 *r++ = clip(y1 + F1*cr);
179                 *g++ = clip(y1 - F2*cb - F3*cr);
180                 *b++ = clip((y1 + F4*cb));
181
182                 *r++ = clip(y2 + F1*cr);
183                 *g++ = clip(y2 - F2*cb - F3*cr);
184                 *b++ = clip((y2 + F4*cb));
185         }
186         free(frm);
187         free(buf);
188         return array;
189
190 Error:
191         for (c = 0; c < 3; c++)
192                 free(a->chans[c]);
193         free(a->cmap);
194         free(array[0]);
195         free(array);
196         free(frm);
197         free(buf);
198         return nil;
199 }
200
201
202 Rawimage**
203 readyuv(int fd, int colorspace)
204 {
205         Rawimage * *a;
206         Biobuf b;
207
208         if (Binit(&b, fd, OREAD) < 0)
209                 return nil;
210         a = Breadyuv(&b, colorspace);
211         Bterm(&b);
212         return a;
213 }
214
215