aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/jpg/readyuv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/jpg/readyuv.c')
-rw-r--r--src/cmd/jpg/readyuv.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/src/cmd/jpg/readyuv.c b/src/cmd/jpg/readyuv.c
new file mode 100644
index 00000000..eae2764e
--- /dev/null
+++ b/src/cmd/jpg/readyuv.c
@@ -0,0 +1,190 @@
+/* readyuv.c - read an Abekas A66 style image file. Steve Simon, 2003 */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <draw.h>
+#include <ctype.h>
+#include "imagefile.h"
+
+/*
+ * ITU/CCIR Rec601 states:
+ *
+ * R = y + 1.402 * Cr
+ * B = Y + 1.77305 * Cb
+ * G = Y - 0.72414 * Cr - 0.34414 * Cb
+ *
+ * using 8 bit traffic
+ * Y = 16 + 219 * Y
+ * Cr = 128 + 224 * Cr
+ * Cb = 128 + 224 * Cb
+ * or, if 10bit is used
+ * Y = 64 + 876 * Y
+ * Cr = 512 + 896 * Cr
+ * Cb = 512 + 896 * Cb
+ */
+
+enum {
+ PAL = 576, NTSC = 486 };
+
+
+static int lsbtab[] = { 6, 4, 2, 0};
+
+static int
+clip(int x)
+{
+ x >>= 18;
+
+ if (x > 255)
+ return 0xff;
+ if (x <= 0)
+ return 0;
+ return x;
+}
+
+
+Rawimage**
+Breadyuv(Biobuf *bp, int colourspace)
+{
+ Dir * d;
+ Rawimage * a, **array;
+ char *e, ebuf[128];
+ ushort * mux, *end, *frm;
+ uchar buf[720 * 2], *r, *g, *b;
+ int y1, y2, cb, cr, sz, c, l, w, base, bits, lines;
+
+ frm = 0;
+ if (colourspace != CYCbCr) {
+ errstr(ebuf, sizeof ebuf); /* throw it away */
+ werrstr("ReadYUV: unknown colour space %d", colourspace);
+ return nil;
+ }
+
+ if ((a = calloc(sizeof(Rawimage), 1)) == nil)
+ sysfatal("no memory");
+
+ if ((array = calloc(sizeof(Rawimage * ), 2)) == nil)
+ sysfatal("no memory");
+ array[0] = a;
+ array[1] = nil;
+
+ if ((d = dirfstat(Bfildes(bp))) != nil) {
+ sz = d->length;
+ free(d);
+ } else {
+ fprint(2, "cannot stat input, assuming 720x576x10bit\n");
+ sz = 720 * PAL * 2L + (720 * PAL / 2L);
+ }
+
+ switch (sz) {
+ case 720 * PAL * 2: // 625 x 8bit
+ bits = 8;
+ lines = PAL;
+ break;
+ case 720 * NTSC * 2: // 525 x 8bit
+ bits = 8;
+ lines = NTSC;
+ break;
+ case 720 * PAL * 2 + (720 * PAL / 2) : // 625 x 10bit
+ bits = 10;
+ lines = PAL;
+ break;
+ case 720 * NTSC * 2 + (720 * NTSC / 2) : // 525 x 10bit
+ bits = 10;
+ lines = NTSC;
+ break;
+ default:
+ e = "unknown file size";
+ goto Error;
+ }
+
+ // print("bits=%d pixels=%d lines=%d\n", bits, 720, lines);
+ //
+ a->nchans = 3;
+ a->chandesc = CRGB;
+ a->chanlen = 720 * lines;
+ a->r = Rect(0, 0, 720, lines);
+
+ e = "no memory";
+ if ((frm = malloc(720 * 2 * lines * sizeof(ushort))) == nil)
+ goto Error;
+
+ for (c = 0; c < 3; c++)
+ if ((a->chans[c] = malloc(720 * lines)) == nil)
+ goto Error;
+
+ e = "read file";
+ for (l = 0; l < lines; l++) {
+ if (Bread(bp, buf, 720 * 2) == -1)
+ goto Error;
+
+ base = l * 720 * 2;
+ for (w = 0; w < 720 * 2; w++)
+ frm[base + w] = ((ushort)buf[w]) << 2;
+ }
+
+
+ if (bits == 10)
+ for (l = 0; l < lines; l++) {
+ if (Bread(bp, buf, 720 / 2) == -1)
+ goto Error;
+
+
+ base = l * 720 * 2;
+ for (w = 0; w < 720 * 2; w++)
+ frm[base + w] |= buf[w / 4] >> lsbtab[w % 4];
+ }
+
+ mux = frm;
+ end = frm + 720 * lines * 2;
+ r = a->chans[0];
+ g = a->chans[1];
+ b = a->chans[2];
+
+ while (mux < end) {
+ cb = *mux++ - 512;
+ y1 = (*mux++ - 64) * 76310;
+ cr = *mux++ - 512;
+ y2 = (*mux++ - 64) * 76310;
+
+ *r++ = clip((104635 * cr) + y1);
+ *g++ = clip((-25690 * cb + -53294 * cr) + y1);
+ *b++ = clip((132278 * cb) + y1);
+
+ *r++ = clip((104635 * cr) + y2);
+ *g++ = clip((-25690 * cb + -53294 * cr) + y2);
+ *b++ = clip((132278 * cb) + y2);
+ }
+ free(frm);
+ return array;
+
+Error:
+
+ errstr(ebuf, sizeof ebuf);
+ if (ebuf[0] == 0)
+ strcpy(ebuf, e);
+ errstr(ebuf, sizeof ebuf);
+
+ for (c = 0; c < 3; c++)
+ free(a->chans[c]);
+ free(a->cmap);
+ free(array[0]);
+ free(array);
+ free(frm);
+ return nil;
+}
+
+
+Rawimage**
+readyuv(int fd, int colorspace)
+{
+ Rawimage * *a;
+ Biobuf b;
+
+ if (Binit(&b, fd, OREAD) < 0)
+ return nil;
+ a = Breadyuv(&b, colorspace);
+ Bterm(&b);
+ return a;
+}
+
+