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