plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }