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
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);
+ }
+ }
+}