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 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 char *e, ebuf[128]; 80 ushort * mux, *end, *frm; 81 uchar *buf, *r, *g, *b; 82 int y1, y2, cb, cr, c, l, w, base; 83 int bits, lines, pixels; 84 int F1, F2, F3, F4; 85 86 frm = nil; 87 buf = nil; 88 if (colourspace != CYCbCr) { 89 errstr(ebuf, sizeof ebuf); /* throw it away */ 90 werrstr("ReadYUV: unknown colour space %d", colourspace); 91 return nil; 92 } 93 94 if ((a = calloc(sizeof(Rawimage), 1)) == nil) 95 sysfatal("no memory"); 96 97 if ((array = calloc(sizeof(Rawimage * ), 2)) == nil) 98 sysfatal("no memory"); 99 array[0] = a; 100 array[1] = nil; 101 102 if ((d = dirfstat(Bfildes(bp))) != nil) { 103 sz = d->length; 104 free(d); 105 } else { 106 fprint(2, "cannot stat input, assuming pixelsx576x10bit\n"); 107 sz = pixels * r601pal * 2L + (pixels * r601pal / 2L); 108 } 109 110 if (looksize("/lib/video.specs", sz, &pixels, &lines, &bits) == -1){ 111 e = "file size not listed in /lib/video.specs"; 112 goto Error; 113 } 114 115 116 a->nchans = 3; 117 a->chandesc = CRGB; 118 a->chanlen = pixels * lines; 119 a->r = Rect(0, 0, pixels, lines); 120 121 e = "no memory"; 122 if ((frm = malloc(pixels*2*lines*sizeof(ushort))) == nil) 123 goto Error; 124 125 for (c = 0; c < 3; c++) 126 if ((a->chans[c] = malloc(pixels*lines)) == nil) 127 goto Error; 128 129 if ((buf = malloc(pixels*2)) == nil) 130 goto Error; 131 132 e = "read file"; 133 for (l = 0; l < lines; l++) { 134 if (Bread(bp, buf, pixels *2) == -1) 135 goto Error; 136 137 base = l*pixels*2; 138 for (w = 0; w < pixels *2; w++) 139 frm[base + w] = ((ushort)buf[w]) << 2; 140 } 141 142 143 if (bits == 10) 144 for (l = 0; l < lines; l++) { 145 if (Bread(bp, buf, pixels / 2) == -1) 146 goto Error; 147 148 149 base = l * pixels * 2; 150 for (w = 0; w < pixels * 2; w++) 151 frm[base + w] |= (buf[w / 4] >> lsbtab[w % 4]) & 3; 152 } 153 154 mux = frm; 155 end = frm + pixels * lines * 2; 156 r = a->chans[0]; 157 g = a->chans[1]; 158 b = a->chans[2]; 159 160 if(pixels * lines != 414720){ // 625 161 F1 = floor(1.402 * (1 << Shift)); 162 F2 = floor(0.34414 * (1 << Shift)); 163 F3 = floor(0.71414 * (1 << Shift)); 164 F4 = floor(1.772 * (1 << Shift)); 165 } 166 else{ // 525 167 F1 = floor(1.5748 * (1 << Shift)); 168 F2 = floor(0.1874 * (1 << Shift)); 169 F3 = floor(0.4681 * (1 << Shift)); 170 F4 = floor(1.8560 * (1 << Shift)); 171 } 172 173 /* 174 * Fixme: fixed colourspace conversion at present 175 */ 176 while (mux < end) { 177 178 cb = *mux++ - 512; 179 y1 = (int)*mux++ << Shift; 180 cr = *mux++ - 512; 181 y2 = (int)*mux++ << Shift; 182 183 *r++ = clip(y1 + F1*cr); 184 *g++ = clip(y1 - F2*cb - F3*cr); 185 *b++ = clip((y1 + F4*cb)); 186 187 *r++ = clip(y2 + F1*cr); 188 *g++ = clip(y2 - F2*cb - F3*cr); 189 *b++ = clip((y2 + F4*cb)); 190 } 191 free(frm); 192 free(buf); 193 return array; 194 195 Error: 196 197 errstr(ebuf, sizeof ebuf); 198 // if (ebuf[0] == 0) 199 strcpy(ebuf, e); 200 errstr(ebuf, sizeof ebuf); 201 202 for (c = 0; c < 3; c++) 203 free(a->chans[c]); 204 free(a->cmap); 205 free(array[0]); 206 free(array); 207 free(frm); 208 free(buf); 209 return nil; 210 } 211 212 213 Rawimage** 214 readyuv(int fd, int colorspace) 215 { 216 Rawimage * *a; 217 Biobuf b; 218 219 if (Binit(&b, fd, OREAD) < 0) 220 return nil; 221 a = Breadyuv(&b, colorspace); 222 Bterm(&b); 223 return a; 224 } 225 226 227