8e8143eef3a1 — pouya@nohup.io tip 7 months ago
add multiline support
4 files changed, 126 insertions(+), 68 deletions(-)

M dat.h
M fns.h
M main.c
M sixel.c
M dat.h +2 -1
@@ 7,5 7,6 @@ typedef struct Sixel Sixel;
 
 struct Sixel {
 	int wd, ht, len;
-	char *buf;
+	int nc, *c;
+	char *buf; /* colour ic starts at buf+ic*len */
 };
  No newline at end of file

          
M fns.h +5 -4
@@ 1,9 1,10 @@ 
 /* sixel.c */
 #define lensxl(wd, ht) ((((ht)-1)/6+1)*(wd))
 
-int initsxl(Sixel *s, int wd, int ht);
+int initsxl(Sixel *s, int wd, int ht, int nc);
 void delsxl(Sixel *s);
-void wtsxl(FILE *f, Sixel *s, int c);
+void wtsxl(FILE *f, Sixel *s);
 
-void setpx(Sixel *s, int x, int y);
-void line(Sixel *s, int x0, int y0, int x1, int y1);
+void setcolour(Sixel *s, int ic, int c);
+void setpx(Sixel *s, int x, int y, int ic);
+void line(Sixel *s, int x0, int y0, int x1, int y1, int ic);

          
M main.c +67 -37
@@ 1,3 1,4 @@ 
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>

          
@@ 9,64 10,85 @@ 
 #define BUFLEN 1024
 #endif
 
+#ifndef MAXLINES
+#define MAXLINES 16
+#endif
+
 #define DEFAULT_HEIGHT 50
 #define DEFAULT_RATIO 3.0
 
 struct {
 	int wd; /* width */
 	int ht; /* height */
-	int c; /* colour */
+	int c[MAXLINES]; /* colourmap */
 	float r; /* aspect ratio */
 } ctx;
 
 int
-rdfseq(float *seq, float *off, float *ran, int len) {
-	int n, nc, done;
-	char bufc[BUFLEN], *c;
+rdfseq(float *seq, float **sseq, float *off, float *ran, int *n, int *nc1) {
+	int i, ib, ic, len, maxlen, eof, eos;
+	char bufc[BUFLEN], *b;
 	float lo, hi;
 
-	done = 0;
-	n = 0;
+
+	memset(sseq, 0, *nc1*(sizeof sseq[0]));
+	ic = 1; *sseq = seq;
+
+	eos = eof = 0;
+	maxlen = len = i = 0;
 	lo = 1.0/0.0;
 	hi = -1.0/0.0;
-	while(!done && n < len) {
-		nc = 0;
-		c = bufc;
-		while(nc++ < BUFLEN) switch(*c++ = getchar()) {
+	while(!eof && i < *n) {
+		ib = 0;
+		b = bufc;
+		while(++ib < (sizeof bufc)/(sizeof bufc[0])) switch(*b++ = getchar()) {
 		case EOF:
-			done = 1;
+			eof = 1;
+		case '>':
+			eos = 1;
 		case '\n':
 		case '\r':
 		case '\t':
 		case ' ':
-			nc--;
-			c--;
-			if(done || nc) goto eofield;
-			break;
+			b--;
+			ib--;
+			goto eofield;
 		default:
 			break;
 		}
 eofield:
-		if(nc == 0) continue;
-		*c = 0;
-		*seq = atof(bufc);
-		if(*seq < lo) lo = *seq;
-		if(*seq > hi) hi = *seq;
-		n++; seq++;
+		if(ib) {
+			*b = 0;
+			*seq = atof(bufc); /* sizeof bufc must be > 1 */
+			if(*seq < lo) lo = *seq;
+			if(*seq > hi) hi = *seq;
+			i++; len++; seq++;
+		}
+		if(eos && ic++ < *nc1 && len) {
+				*++sseq = seq;
+				if(maxlen < len) maxlen=len ;
+				len = 0;
+			}
+		eos=0;
 	}
 
 	*off = lo;
 	*ran = hi - lo;
-	return n;
+	*n = i;
+	*nc1 = ic;
+	return maxlen;
 }
 
 void
 init(int argc, char **argv) {
-	char *p = *argv;
+	char *p;
+	int ic;
 
+	p = *argv;
+	ic = 0;
 	ctx.ht = DEFAULT_HEIGHT;
 	ctx.r = DEFAULT_RATIO;
-	ctx.wd = -1;
+	memset(ctx.c, 0, sizeof ctx.c);
 	while(--argc) {
 		if(strlen(*++argv) < 2 || **argv != '-') goto usage;
 		switch((*argv)[1]) {

          
@@ 80,7 102,7 @@ init(int argc, char **argv) {
 			break;
 		case 'c': /* colour */
 			if(!--argc) goto usage;
-			ctx.c = atoi(*++argv);
+			ctx.c[ic++ % ((sizeof ctx.c)/(sizeof ctx.c[0]))] = atoi(*++argv);
 			break;
 		default:
 			goto usage;

          
@@ 90,33 112,41 @@ init(int argc, char **argv) {
 	return;
 
 usage:
-	fprintf(stderr, "usage: %s -h height -r ratio -c colour\n\theight: height in pixels\n\tratio:  aspect ratio\n\tcolour: rgb as integer\n", p);
+	fprintf(stderr, "usage: %s -h height -r ratio -c colour0 -c colour1 ...\n\theight: height in pixels\n\tratio:  aspect ratio\n\tcolour: rgb as integer\n", p);
 	exit(1);
 }
 
 int
 main(int argc, char **argv) {
-	int i, j, i0, j0, n, done;
-	float seq[BUFLEN], *y, off, ran;
+	int i, j, i0, j0, n, len, ic, nc1;
+	float seq[BUFLEN], *sseq[MAXLINES+1], **sy, *y, off, ran, dx, cy;
 	Sixel s;
 
 	init(argc, argv);
 
-	n = rdfseq(seq, &off, &ran, BUFLEN);
+	n = (sizeof seq)/(sizeof seq[0]);
+	nc1 = (sizeof sseq)/(sizeof sseq[0]); /* nc1 is num lines + 1 as sseq has one more entry than num lines */
+	len = rdfseq(seq, sseq, &off, &ran, &n, &nc1);
 
-	if(initsxl(&s, ctx.wd, ctx.ht)) {
+	if(initsxl(&s, ctx.wd, ctx.ht, nc1-1)) {
 		fprintf(stderr, "out of memory.\n");
 		exit(1);
 	}
 
-	i0=0;
-	j0 = (float)(ctx.ht-1)*(*seq-off)/ran;
-	for(y=seq, i=0; i<n; y++, i++) {
-		j = (float)(ctx.ht-1)*(*y-off)/ran;
-		line(&s, i0*ctx.wd/n, j0, i*ctx.wd/n, j);
-		i0 = i; j0 = j;
+	cy = isfinite(ran) ? (float)(ctx.ht-1)/ran : 0;
+	for(sy=sseq, ic=0; ic<nc1-1; sy++, ic++) {
+		if((len = *(sy+1)-*sy) < 2) continue;
+		dx = (float)ctx.wd / (float)(len-1);
+		i0=0;
+		j0 =cy*(**sy-off);
+		setcolour(&s, ic, ctx.c[ic]);
+		for(i=0, y=*sy; y<*(sy+1); i++, y++) {
+			if(!isfinite(j = cy*(*y-off))) j=0;
+			line(&s, i0*dx, j0, i*dx, j, ic);
+			i0 = i; j0 = j;
+		}
 	}
-	wtsxl(stdout, &s, ctx.c);
+	wtsxl(stdout, &s);
 	delsxl(&s);
 
 	return 0;

          
M sixel.c +52 -26
@@ 6,54 6,80 @@ 
 #include "fns.h"
 
 int
-initsxl(Sixel *s, int wd, int ht) {
-	if((s->buf = malloc(lensxl(wd, ht))) == 0) return -1;
+initsxl(Sixel *s, int wd, int ht, int nc) {
+	if((s->c = malloc(nc*sizeof(int))) == 0) return -1;
+	if((s->buf = malloc(nc*lensxl(wd, ht))) == 0) {
+		free(s->c);
+		return -1;
+	}
+
 	s->wd = wd;
 	s->ht = ht;
 	s->len = lensxl(wd, ht);
-	memset(s->buf, 63, s->len);
+	s->nc = nc;
+
+	memset(s->c, 0, nc*sizeof(int));
+	memset(s->buf, 63, nc*s->len);
 
 	return 0;
 }
 
 void
 delsxl(Sixel *s) {
+	free(s->c);
 	free(s->buf);
+	s->c = nil;
 	s->buf = nil;
-	s->wd = s->ht = s->len = 0;
+	s->wd = s->ht = s->len = s->nc = 0;
 }
 
 void
-wtsxl(FILE *f, Sixel *s, int c) {
-	int i;
+wtsxl(FILE *f, Sixel *s) {
+	int i, ic;
 	char *b;
 
 	fprintf(f, "%cPq", ESC);
-	fprintf(f, "#0;2;%d;%d;%d",
-		((c>>16)&0xff)*100/255,
-		((c>>8)&0xff)*100/255,
-		(c&0xff)*100/255);
-	fputs("#0", f);
-	for(b = s->buf, i=0; i<s->len; b++, i++) {
+	for(ic=0; ic<s->nc; ic++) {
+		fprintf(f, "#%d;2;%d;%d;%d", ic,
+			((s->c[ic]>>16)&0xff)*100/255,
+			((s->c[ic]>>8)&0xff)*100/255,
+			(s->c[ic]&0xff)*100/255);
+	}
+	fputs("\n#0", f);
+	for(b = s->buf, ic=0, i=0; i<s->nc*s->len; b++, i++) {
 		fputc(*b, f);
-		if(i%s->wd == s->wd-1) fputs("$-", f);
+		if(i%s->wd == s->wd-1) {
+			fputc('$', f);
+			if(++ic==s->nc) {
+				ic=0;
+				b -= (s->nc-1)*s->len; 
+				fputs("-", f);
+			} else {
+				b += s->len - s->wd;
+			}
+			fprintf(f, "\n#%d", ic);
+		}
 	}
 	fprintf(f, "%c\\", ESC);
 }
 
 void
-setpx(Sixel *s, int x, int y) {
-	char c;
-
-	y = s->ht-y;
-	c = s->buf[x+s->wd*(y/6)] - 63;
-	c |= 1<<y%6;
-	c += 63;
-	s->buf[x+s->wd*(y/6)] = c;
+setcolour(Sixel *s, int ic, int c) {
+	s->c[ic] = c;
 }
 
 void
-line(Sixel *s, int x0, int y0, int x1, int y1) {
+setpx(Sixel *s, int x, int y, int ic) {
+	char *sx;
+
+	if(x<0 || x>=s->wd || y<0 || y>=s->ht) return;
+	y = s->ht-y;
+	sx = s->buf+x+s->wd*(y/6)+ic*s->len;
+	*sx = ((*sx-63)|(1<<y%6)) + 63;
+}
+
+void
+line(Sixel *s, int x0, int y0, int x1, int y1, int ic) {
 	float dx, dy, r;
 	int sdx, sdy, u;
 	int i;

          
@@ 64,8 90,8 @@ line(Sixel *s, int x0, int y0, int x1, i
 	sdx = dx > 0 ? 1 : -1;
 	sdy = dy > 0 ? 1 : -1;
 
-	setpx(s, x0, y0);
-	setpx(s, x1, y1);
+	setpx(s, x0, y0, ic);
+	setpx(s, x1, y1, ic);
 	if(dx*sdx > dy*sdy) {
 		if(x0>x1) {
 			u = x0; x0 = x1; x1 = u;

          
@@ 75,7 101,7 @@ line(Sixel *s, int x0, int y0, int x1, i
 		}
 		r = dx > 0 ? dy/dx : 0;
 		for(i=x0; i<x1; i++) {
-			setpx(s, i, (i-x0)*r+y0);
+			setpx(s, i, (i-x0)*r+y0, ic);
 		}
 	} else {
 		if(y0>y1) {

          
@@ 86,7 112,7 @@ line(Sixel *s, int x0, int y0, int x1, i
 		}
 		r = dy > 0 ? dx/dy : 0;
 		for(i=y0; i<y1; i++) {
-			setpx(s, (i-y0)*r+x0, i);
+			setpx(s, (i-y0)*r+x0, i, ic);
 		}
 	}
 }