ab0dbb103378 — pouya@nohup.io 7 months ago
initial commit
6 files changed, 273 insertions(+), 0 deletions(-)

A => Makefile
A => dat.h
A => data.txt
A => fns.h
A => main.c
A => sixel.c
A => Makefile +23 -0
@@ 0,0 1,23 @@ 
+CC=pcc
+LD=pcc
+
+CCFLAGS=-O
+LDFLAGS=-static
+
+TARG=sparkle
+OFILES=main.o sixel.o
+
+all: ${TARG}
+
+clean:
+	rm -f *.o ${TARG}
+
+.SUFFIXES: .c .o
+
+.c.o:
+	${CC} ${CCFLAGS} -c ${.IMPSRC} -o ${.TARGET}
+
+${TARG}: ${OFILES}
+	${LD} ${LDFLAGS} ${.ALLSRC} -o ${.TARGET}
+
+.PHONY: all clean

          
A => dat.h +11 -0
@@ 0,0 1,11 @@ 
+#define nil (void *)0
+
+/* sixel.c */
+typedef struct Sixel Sixel;
+
+#define ESC 27
+
+struct Sixel {
+	int wd, ht, len;
+	char *buf;
+};
  No newline at end of file

          
A => data.txt +15 -0
@@ 0,0 1,15 @@ 
+0
+1
+2
+3
+4
+5
+6
+7
+8
+4
+2
+1
+2
+4
+8

          
A => fns.h +9 -0
@@ 0,0 1,9 @@ 
+/* sixel.c */
+#define lensxl(wd, ht) ((((ht)-1)/6+1)*(wd))
+
+int initsxl(Sixel *s, int wd, int ht);
+void delsxl(Sixel *s);
+void wtsxl(FILE *f, Sixel *s, int c);
+
+void setpx(Sixel *s, int x, int y);
+void line(Sixel *s, int x0, int y0, int x1, int y1);

          
A => main.c +123 -0
@@ 0,0 1,123 @@ 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dat.h"
+#include "fns.h"
+
+#ifndef BUFLEN
+#define BUFLEN 1024
+#endif
+
+#define DEFAULT_HEIGHT 50
+#define DEFAULT_RATIO 3.0
+
+struct {
+	int wd; /* width */
+	int ht; /* height */
+	int c; /* colour */
+	float r; /* aspect ratio */
+} ctx;
+
+int
+rdfseq(float *seq, float *off, float *ran, int len) {
+	int n, nc, done;
+	char bufc[BUFLEN], *c;
+	float lo, hi;
+
+	done = 0;
+	n = 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()) {
+		case EOF:
+			done = 1;
+		case '\n':
+		case '\r':
+		case '\t':
+		case ' ':
+			nc--;
+			c--;
+			if(done || nc) goto eofield;
+			break;
+		default:
+			break;
+		}
+eofield:
+		if(nc == 0) continue;
+		*c = 0;
+		*seq = atof(bufc);
+		if(*seq < lo) lo = *seq;
+		if(*seq > hi) hi = *seq;
+		n++; seq++;
+	}
+
+	*off = lo;
+	*ran = hi - lo;
+	return n;
+}
+
+void
+init(int argc, char **argv) {
+	char *p = *argv;
+
+	ctx.ht = DEFAULT_HEIGHT;
+	ctx.r = DEFAULT_RATIO;
+	ctx.wd = -1;
+	while(--argc) {
+		if(strlen(*++argv) < 2 || **argv != '-') goto usage;
+		switch((*argv)[1]) {
+		case 'h': /* height */
+			if(!--argc) goto usage;
+			ctx.ht = atoi(*++argv);
+			break;
+		case 'r': /* aspect ratio */
+			if(!--argc) goto usage;
+			ctx.r = atof(*++argv);
+			break;
+		case 'c': /* colour */
+			if(!--argc) goto usage;
+			ctx.c = atoi(*++argv);
+			break;
+		default:
+			goto usage;
+		}
+	}
+	ctx.wd = ctx.r*ctx.ht;
+	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);
+	exit(1);
+}
+
+int
+main(int argc, char **argv) {
+	int i, j, i0, j0, n, done;
+	float seq[BUFLEN], *y, off, ran;
+	Sixel s;
+
+	init(argc, argv);
+
+	n = rdfseq(seq, &off, &ran, BUFLEN);
+
+	if(initsxl(&s, ctx.wd, ctx.ht)) {
+		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;
+	}
+	wtsxl(stdout, &s, ctx.c);
+	delsxl(&s);
+
+	return 0;
+}
  No newline at end of file

          
A => sixel.c +92 -0
@@ 0,0 1,92 @@ 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dat.h"
+#include "fns.h"
+
+int
+initsxl(Sixel *s, int wd, int ht) {
+	if((s->buf = malloc(lensxl(wd, ht))) == 0) return -1;
+	s->wd = wd;
+	s->ht = ht;
+	s->len = lensxl(wd, ht);
+	memset(s->buf, 63, s->len);
+
+	return 0;
+}
+
+void
+delsxl(Sixel *s) {
+	free(s->buf);
+	s->buf = nil;
+	s->wd = s->ht = s->len = 0;
+}
+
+void
+wtsxl(FILE *f, Sixel *s, int c) {
+	int i;
+	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++) {
+		fputc(*b, f);
+		if(i%s->wd == s->wd-1) fputs("$-", f);
+	}
+	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;
+}
+
+void
+line(Sixel *s, int x0, int y0, int x1, int y1) {
+	float dx, dy, r;
+	int sdx, sdy, u;
+	int i;
+
+	dx = x1-x0;
+	dy = y1-y0;
+
+	sdx = dx > 0 ? 1 : -1;
+	sdy = dy > 0 ? 1 : -1;
+
+	setpx(s, x0, y0);
+	setpx(s, x1, y1);
+	if(dx*sdx > dy*sdy) {
+		if(x0>x1) {
+			u = x0; x0 = x1; x1 = u;
+			u = y0; y0 = y1; y1 = u;
+			dx = x1-x0;
+			dy = y1-y0;	
+		}
+		r = dx > 0 ? dy/dx : 0;
+		for(i=x0; i<x1; i++) {
+			setpx(s, i, (i-x0)*r+y0);
+		}
+	} else {
+		if(y0>y1) {
+			u = x0; x0 = x1; x1 = u;
+			u = y0; y0 = y1; y1 = u;
+			dx = x1-x0;
+			dy = y1-y0;	
+		}
+		r = dy > 0 ? dx/dy : 0;
+		for(i=y0; i<y1; i++) {
+			setpx(s, (i-y0)*r+x0, i);
+		}
+	}
+}