CD001UTF8 9CD 00 fg"ddk '9VOLUMESET 9PUBLISHER DUMP9660 DUMP9660 2007091800223900200709180022390000000000000000000000000000000000ÿCD001#include #include #include #include #include "bioutils.h" /* * fetch a non-comment character. */ static int Bgetch(Biobufhdr *b) { int c; for(;;) { c = Bgetc(b); if(c == '#') { while((c = Bgetc(b)) != Beof && c != '\n') ; } return c; } } /* * fetch a nonnegative decimal integer. */ static int Bgetint(Biobufhdr *b) { int c; int i; while((c = Bgetch(b)) != Beof && !isdigit(c)) ; if(c == Beof) return -1; i = 0; do { i = i*10 + (c-'0'); } while((c = Bgetch(b)) != Beof && isdigit(c)); return i; } static int Bgetdecimalbit(Biobufhdr *b) { int c; while((c = Bgetch(b)) != Beof && c != '0' && c != '1') ; if(c == Beof) return -1; return c == '1'; } static int Bgetbit(Biobufhdr *b) { if(nbit == 0) { nbit = 8; bitc = Bgetc(b); if(bitc == -1) return -1; } nbit--; return (bitc >> (nbit-1)) & 0x1; } static void Bflushbit(Biobufhdr*) { nbit = 0; } // bioutils.c /* * fetch a non-comment character. */ static int Bgetch(Biobufhdr *b); /* * fetch a nonnegative decimal integer. */ static int Bgetint(Biobufhdr *b); static int Bgetdecimalbit(Biobufhdr *b); static int bitc, nbit; static int Bgetbit(Biobufhdr *b); static void Bflushbit(Biobufhdr*);#include #include # include #include "ifslib.h" char * dirname(char *folder) { char *path; char *pr; char *dir; if(!folder) return nil; path = smprint("%s", folder); pr = utfrrune(path, '/'); if(pr){ *pr = 0; dir = smprint("%s/", path); } else dir = smprint("./"); free(path); return dir; } uchar * resize_nearest_neighbour(uchar *data_in, Rectangle *src, Rectangle *dst) { uchar *data_out; float xs, ys; int nx, ny, ox, oy, i; int ow, oh, nw, nh; if ((!src) || (!dst)) return nil; ow = src->max.x - src->min.x; oh = src->max.y - src->min.y; nw = dst->max.x - dst->min.x; nh = dst->max.y - dst->min.y; data_out = emalloc(nw * nh); xs = (float)ow / (float)nw; ys = (float)oh / (float)nh; i = 0; for (ny=0; nymax.x - src->min.x; oh = src->max.y - src->min.y; nw = dst->max.x- dst->min.x; nh = dst->max.y - dst->min.y; data_out = emalloc(nw * nh); xs = (float)ow / (float)nw; ys = (float)oh / (float)nh; i = 0; for (ny=0; ny #include #include "complex.h" float maxf(float a, float b) { if(a > b) return a; return b; } int maxi(int a, int b) { if(a > b) return a; return b; } float scaleFloat(int i, float f) { float k = (float)(pow(2.0, i)); return f * k; } void ccp(Complex *a, Complex *b) { a->r = b->r; a->i = b->i; } int exponent(float x) { int e; frexp(x, &e); return e; } void cmul(Complex *r, Complex *a, Complex *b) { r->r = a->r * b->r - a->i * b->i; r->i = a->r * b->i + a->i * b->r; } void cdiv(Complex *r, Complex *a, Complex *b) { float d; Complex c; cscaleFloat(&c, b, -maxi(exponent(b->r), exponent(b->i))); d = b->r * c.r + b->i * c.i; r->r = (a->r * c.r + a->i * c.i) / d; r->i = (a->i * c.r - a->r * c.i) / d; } void cscale(Complex *r, Complex *a, float s) { r->r = a->r * s; r->i = a->i * s; } void cscaleFloat(Complex *r, Complex *a, int i) { r->r = scaleFloat(i, a->r); r->i = scaleFloat(i, a->i); } void cadd(Complex *r, Complex *a, Complex *b) { r->r = a->r + b->r; r->i = a->i + b->i; } void csub(Complex *r, Complex *a, Complex *b) { r->r = a->r - b->r; r->i = a->i - b->i; } void cexp(Complex *r, Complex *c) { float x = exp(c->r); r->r = x * cos(c->i); r->i = x * sin(c->i); } void cprint(char *name, Complex *c) { print("%s %0.2f :+ %0.2f\n", name, c->r, c->i); } float magnitude(Complex *z) { int k; float kx, ky; k = maxi(exponent(z->r), exponent(z->i)); kx = scaleFloat(-k, z->r); ky = scaleFloat(-k, z->i); return scaleFloat(k, sqrt(ky*ky + kx*kx)); } float phase(Complex *z) { if(z->r == 0 && z->i == 0) return 0; return atan2(z->i, z->r); } void clog(Complex *r, Complex *z) { r->r = log(magnitude(z)); r->i = phase(z); } float cradius(Complex *z) { return sqrt(z->r * z->r + z->i * z->i); } typedef struct Complex Complex; struct Complex { float r; float i; }; void ccp(Complex *a, Complex *b); void cmul(Complex *r, Complex *a, Complex *b); void cdiv(Complex *r, Complex *a, Complex *b); void cscale(Complex *r, Complex *a, float s); void cscaleFloat(Complex *r, Complex *a, int i); void cadd(Complex *r, Complex *a, Complex *b); void csub(Complex *r, Complex *a, Complex *b); void cexp(Complex *r, Complex *c); void cprint(char *name, Complex *c); void clog(Complex *r, Complex *c); float phase(Complex *z); float magnitude(Complex *z); float cradius(Complex *z); #include #include # include #include "ifslib.h" void main(int argc, char **argv) { char *errstr = nil; int pixels, x, y, p, py, pval; int divisor, cx, cy, cw, ch, cdx, cdy, ci, bias; uchar *data_in, *data_out; char *filter; int pixel, i, iy; int width, height; int conv[9] = { [0] = -1, [1] = 0, [2] = -1, [3] = 0, [4] = 7, [5] = 0, [6] = -1, [7] = 0, [8] = -1 }; print("%d\n", sizeof(conv) / sizeof(int)); exits(0); /* int conv[25] = { [0] = 2 , [1] = 4 , [2] = 5 , [3] = 4 , [4] = 2 , [5] = 4 , [6] = 9 , [7] = 12 , [8] = 9 , [9] = 4 , [10] = 5 , [11] = 12 , [12] = 15 , [13] = 12 , [14] = 5 , [15] = 4 , [16] = 9 , [17] = 12 , [18] = 9 , [19] = 4 , [20] = 2 , [21] = 4 , [22] = 5 , [23] = 4 , [24] = 2 }; */ divisor = 0; for(i=0; i<25; i++) divisor += conv[i]; bias = 0; ch = cw = 5; if(argc != 2) bail("usage : channel_name"); width = get_width(); height = get_height(); pixels = width * height; data_in = read_channel_data(argv[1], pixels); data_out = (uchar*) emalloc(pixels); cdx = (ch-1) >> 1; cdy = (cw-1) >> 1; for(y = cdy; y< height - cdy; y++) { i = y * width + cdx; for(x= cdx; x< width - cdy; x++) { ci = 0; pval = 0; for (cy = -cdy; cy <= cdy; cy ++) { py = (y + cy) * width; for (cx = -cdx; cx <= cdx; cx ++) { p = py + x + cx; pval += conv[ci] * data_in[p]; ci++; } } data_out[i++] = bias + pval / divisor; } } errstr = write_channel_data(argv[1], pixels, data_out); free(data_in); free(data_out); bail(errstr); } #include #include #include #include #include #include // #include "ifslib.h" // 8c cp_subfont_header.c && 8l cp_subfont_header.8 && mv 8.out cp_subfont_header static int bitc, nbit; /* * fetch a non-comment character. */ static int Bgetch(Biobufhdr *b) { int c; for(;;) { c = Bgetc(b); if(c == '#') { while((c = Bgetc(b)) != Beof && c != '\n') ; } return c; } } /* * fetch a nonnegative decimal integer. */ static int Bgetint(Biobufhdr *b) { int c; int i; while((c = Bgetch(b)) != Beof && !isdigit(c)) ; if(c == Beof) return -1; i = 0; do { i = i*10 + (c-'0'); } while((c = Bgetch(b)) != Beof && isdigit(c)); return i; } static int Bgetdecimalbit(Biobufhdr *b) { int c; while((c = Bgetch(b)) != Beof && c != '0' && c != '1') ; if(c == Beof) return -1; return c == '1'; } static int Bgetbit(Biobufhdr *b) { if(nbit == 0) { nbit = 8; bitc = Bgetc(b); if(bitc == -1) return -1; } nbit--; return (bitc >> (nbit-1)) & 0x1; } static void Bflushbit(Biobufhdr*) { nbit = 0; } void main (int argc, char **argv) { int font_fd ; Biobuf b; uchar *buff; char *chan; Rectangle r; int fd_src, fd_target; int nexty, blocklength; int i, n, height, ascent; fd_src = open(argv[1], OREAD); fd_target = open(argv[2], ORDWR|OTRUNC); Binit(&b, fd_src, OREAD); buff = (uchar*)Brdstr(&b, '\n', 1); free(buff); chan = (char*) malloc(12); Bread(&b, chan, 12); free(chan); r.min.x = Bgetint(&b); r.min.y = Bgetint(&b); r.max.x = Bgetint(&b); r.max.y = Bgetint(&b); nexty = Bgetint(&b); blocklength = Bgetint(&b); while(nexty < r.max.y) { Bseek(&b, blocklength, 1); nexty = Bgetint(&b); blocklength = Bgetint(&b); } Bseek(&b, blocklength, 1); chan = (char*)malloc(13); Bread(&b, chan, 12); chan[12] = 0; n = atoi(chan); print("n : '%s'\n", chan); write(fd_target, buff, 12); Bread(&b, chan, 12); write(fd_target, buff, 12); Bread(&b, chan, 12); write(fd_target, buff, 12); free(chan); buff = (uchar*)malloc(6); if(buff == nil) exits("no memory for 6 bytes!"); for(i=0; i<=n; i++) { Bread(&b, buff, 6); write(fd_target, buff, 6); } free(buff); close(fd_src); close(fd_target); exits(0); } #include "droste.h" void set_bounds(Pair *b) { if(RETWIST) { b->a.x = b->a.y = -R2; b->b.x = b->b.y = R2; } else { b->a.x = -log(R2 / R1); b->a.y = 0; b->b.x = 2.1 * PI; b->b.y = log(R2 / R1); } } void fill_beta(Complex *beta) { float a = atan(P1 / P2 * log(R2 / R1) / (2 * PI)); float f = cos(a); Complex e, c = {0, a}; cexp(&e, &c); cscale(beta, &e, f); } void fill_middle(Complex *m, Pair *b) { m->r = 0.5 * (b->a.x + b->b.x); m->i = 0.5 * (b->a.y + b->b.y); } void fill_z(Complex *z, Pair *b, float xmid, int x, int y) { float xmin, xmax, xrange, yrange; xrange = b->b.x- b->a.x; yrange = b->b.y - b->a.y; xrange = yrange * aspectRatio; xmin = xmid - 0.5 * xrange; xmax = xmid + 0.5 * xrange; z->r = xmin + (xmax - xmin) * (x + WIDTH / 2) / WIDTH; z->i = b->a.y + (b->b.y - b->a.y) * (y + HEIGHT / 2) / HEIGHT; } void set_z_zinitial(Complex *z, Complex *zinitial, Complex *xymiddle) { Complex z_minus_xmiddle, zc, ze; Complex crotate; if(RETWIST) { ccp(zinitial, z); csub(&zc, z, xymiddle); cscale(&z_minus_xmiddle, &zc, 1.0/ZOOM); crotate.r = 0; crotate.i = -ROTATE; cmul(&zc, &z_minus_xmiddle, &crotate); cadd(z, &zc, xymiddle); } else { cexp(&zc, z); cscale(&ze, &zc, ZOOM * R1); crotate.r = 0; crotate.i = ROTATE; cmul(zinitial, &ze, &crotate); } } void set_z2(Complex *z2, Complex *z) { Complex c; if(RETWIST) { ccp(z2, z); } else { cscale(&c, z, 1.0 / R1); clog(z2, &c); } } void apply_z2_to_z(Complex *z, Complex *z2, Complex *beta) { Complex c, d; cscale(&d, z2, P2); cdiv(&c, &d, beta); cexp(&d, &c); cscale(z, &d, R1); } int get_direction(Complex *z) { float radius = cradius(z); if (radius < R1) return -1; if (radius > R2) return 1; return 0; } float get_angle(void) { float a; a = 2 * PI * P2; return P1 > 0 ? a : -a; } void fill_ratio(Complex *ratio, int sign, float angle) { Complex a, ea; float rr = 1; if (sign < 0) { a.r = 0; a.i = angle; rr = R2 / R1; } else { a.r = 0; a.i = -angle; rr = R1 / R2; } cexp(&ea, &a); cscale(ratio, &ea, rr); } void sample_point(Complex *beta, int x, int y, float *ix, float *iy) { Pair bounds; Complex xymiddle; Complex z, zinitial, z2; Complex ratio; int direction; int i; float angle; set_bounds(&bounds); fill_middle(&xymiddle, &bounds); fill_z(&z, &bounds, xymiddle.r, x, y); set_z_zinitial(&z, &zinitial, &xymiddle); set_z2(&z2, &z); apply_z2_to_z(&z, &z2, beta); int minDimension = WIDTH < HEIGHT ? WIDTH : HEIGHT; *ix = minDimension / 2 * z.r; *iy = minDimension / 2 * z.i; direction = get_direction(&z); angle = get_angle(); fill_ratio(&ratio, direction, angle); MAXITERATION=0; for(i = 0; direction != 0 && i < MAXITERATION; i++, direction = get_direction(&z)) { cmul(&z2, &z, &ratio); ccp(&z2, &z); *ix = minDimension / 2 * z.r; *iy = minDimension / 2 * z.i; } } void main(int argc, char **argv) { char *errstr = nil; int pixels, i, x, y; uchar *data_in, *data_out; float ix, iy; Complex beta; ARGBEGIN{ case 'i': R1 = atof(ARGF()); break; case 'o' : R2 = atof(ARGF()); break; case 's' : P1 = atoi(ARGF()); break; case 'p' : P2 = atoi(ARGF()); break; case 'z' : ZOOM = atof(ARGF()); break; case 'r' : ROTATE = atof(ARGF()); break; case 'w' : RETWIST = 0; break; }ARGEND; if(argc != 1) bail("usage : droste [-i inner_radius -o outer_radius -s strands -p periodicity -z zoom -r rotate -w dont_retwist] channel"); WIDTH = get_width(); HEIGHT = get_height(); pixels = WIDTH * HEIGHT; data_in = read_channel_data(argv[0], pixels); data_out = (uchar*) emalloc(pixels); aspectRatio = (float)WIDTH / (float)HEIGHT; fill_beta(&beta); i = 0; for(y = 0; y < HEIGHT; y++) { for(x = 0; x < WIDTH; x++) { sample_point(&beta, x, y, &ix, &iy); data_out[i++] = get_pixel(data_in, WIDTH, HEIGHT, ix, iy, 1); } } errstr = write_channel_data(argv[0], pixels, data_out); free(data_out); free(data_in); }#include #include #include #include "complex.h" #include "ifslib.h" float EPSILON = .01; int WIDTH; int HEIGHT; float aspectRatio; // 0 < r1 < r2 < 1 determines the inner and outer fractional radii of the annulus which will be wrapped // r1 = user_float("inner radius", 0, 1); // r2 = user_float("outer radius", 0, 1); float R1 = .115; float R2 = .7; int P1 = 1; // number of strands int P2 = 1; // periodicity // procedural scaling and rotation float ZOOM = 1.0; // user_float("zoom", 0.1, 10); float ROTATE = PI / 180 * 1.0; //user_float("rotate", 0, 360); int RETWIST = 1; int MAXITERATION = 10; typedef struct Range Range; struct Range { float min; float max; }; typedef struct Tuple Tuple; struct Tuple { float a; float b; }; typedef struct Cartesian Cartesian; struct Cartesian { float x; float y; }; typedef struct Pair Pair; struct Pair { Cartesian a; Cartesian b; }; typedef struct Polar Polar; struct Polar { float r; float a; }; #include #include #include #include #include #include // #include "ifslib.h" // 8c ekko.c && 8l ekko.8 && ./8.out static int bitc, nbit; /* * fetch a non-comment character. */ static int Bgetch(Biobufhdr *b) { int c; for(;;) { c = Bgetc(b); if(c == '#') { while((c = Bgetc(b)) != Beof && c != '\n') ; } return c; } } /* * fetch a nonnegative decimal integer. */ static int Bgetint(Biobufhdr *b) { int c; int i; while((c = Bgetch(b)) != Beof && !isdigit(c)) ; if(c == Beof) return -1; i = 0; do { i = i*10 + (c-'0'); } while((c = Bgetch(b)) != Beof && isdigit(c)); return i; } int Bget11int(Biobufhdr *b) { int i; char *chan = (char*) malloc(13); Bread(b, chan, 12); chan[11] = 0; i = atoi(chan); free(chan); return i; } void main (void) { int font_fd ; Biobuf b; uchar *buff; char *chan; Rectangle r; int fd; int i, n, height, ascent; int x, top, bottom, left, width; fd = open("/usr/font_m8/l_10646.20.00a0.layout", OREAD); Binit(&b, fd, OREAD); n = Bget11int(&b); height = Bget11int(&b); ascent = Bget11int(&b); print("n:%d height:%d ascent:%d \n", n, height, ascent); buff = (uchar*)malloc(6); for(i=0; i<=n; i++) { if (Bread(&b, buff, 6) != 6) break; x = GBIT16(&buff[0]); top = buff[2]; bottom = buff[3]; left = buff[4]; width = buff[5]; print("x:%d top:%d bottom:%d left:%d width:%d\n", x, top, bottom, left, width); } close(fd); exits(0); } #include #include #define PBIT16(p,v) (p)[0]=(v);(p)[1]=(v)>>8 // 8c export_tga.c && 8l export_tga.8 && mv 8.out export_tga && ./tester.rc int tga_fd; uchar identsize=0; uchar colourmaptype=0; uchar imagetype=0; ushort colourmapstart=0; ushort colourmaplength=0; uchar colourmapbits=0; ushort xstart=0; ushort ystart=0; ushort width=0; ushort height=0; uchar bits=0; uchar descriptor=0; char *comment=nil; void * emalloc(ulong size) { void* m; m = malloc(size); if(m) return m; exits("out of memory"); return nil; // stop compiler warning } int write_header(void) { uchar header[18]; header[0] = identsize; header[1] = colourmaptype; header[2] = imagetype; PBIT16(&header[3], colourmapstart); PBIT16(&header[5], colourmaplength); header[7] = colourmapbits; PBIT16(&header[8], xstart); PBIT16(&header[10], ystart); PBIT16(&header[12], width); PBIT16(&header[14], height); header[16] = bits; header[17] = descriptor; return write(tga_fd, header, 18); } char * write_rgb(void) { int fdr, fdg, fdb; uchar *buffer, *rbuffer, *gbuffer, *bbuffer; ushort row, rowbytes, i, k, c; long readbytes=0; fdr = open("red", OREAD); fdg = open("green", OREAD); fdb = open("blue", OREAD); if(fdr < 0 || fdg < 0 || fdb < 0) return smprint("red or green or blue not opened"); rowbytes = 3 * width; buffer = (uchar*) emalloc(rowbytes); bbuffer = (uchar*) emalloc(width); rbuffer = (uchar*) emalloc(width); gbuffer = (uchar*) emalloc(width); for(row=0; row < height; row++) { readbytes = read(fdb, bbuffer, width); readbytes += read(fdr, rbuffer, width); readbytes += read(fdg, gbuffer, width); if(readbytes != rowbytes) break; i = k = 0; for(c=0; c < width; c++) { buffer[k++] = bbuffer[i]; buffer[k++] = rbuffer[i]; buffer[k++] = gbuffer[i]; i++; } write(tga_fd, buffer, rowbytes); } close(fdb); close(fdr); close(fdg); free(buffer); free(bbuffer); free(rbuffer); free(gbuffer); if(readbytes == rowbytes) return nil; return smprint("bad read, not enough data"); } void usage(void) { fprint(2, "usage: export_tga filename\n"); exits("usage"); } void main(int argc, char **argv) { char *errstr = nil; if(argc != 2) usage(); tga_fd = open(argv[1], OWRITE|OTRUNC); if(tga_fd < 0) { fprint(2, "open for write failed : %s\n", argv[1]); exits("open failed"); } imagetype = 2; bits = 24; descriptor = 32; width = 500; height = 500; if(write_header() == 18) { if(write_rgb() == nil) if(comment) write(tga_fd, comment, strlen(comment)); } close(tga_fd); exits(errstr); }#!/bin/rc target = /usr/font_m8 src =/usr/matt/ink/l_10646/l_10646.20.font src_dir = `{basename -d $src} src_font = `{basename $src} cp $src $target for (subfont in `{awk ' $3 != "" { print $3 } ' $src}) { rm -f $target/$subfont rm -f $target/$subfont.layout if (test -e $src_dir/$subfont) { toppm $src_dir/$subfont | ppm -9 > $target/$subfont touch $target/$subfont.layout /usr/matt/imagefs_src/cp_subfont_header $src_dir/$subfont $target/$subfont.layout } if not { toppm $src_dir/$subfont.1 | ppm -9 > $target/$subfont touch $target/$subfont.layout /usr/matt/imagefs_src/cp_subfont_header $src_dir/$subfont.1 $target/$subfont.layout } } #include #include #include #include "ifslib.h" int min_int(int a, int b) { if ( a < b ) return a; return b; } int max_int(int a, int b) { if ( a > b ) return a; return b; } int get_width(void) { return read_atoi_from_file("width") ; } int get_height(void) { return read_atoi_from_file("height"); } int set_width(int w) { return write_int_to_file("width", w); } int set_height(int h) { return write_int_to_file("height", h); } int write_int_to_file(char *filename, int i) { int fd; char *t; if(!filename) return 0; t = smprint("%d\n", i); fd = get_fd(filename, OWRITE|OTRUNC); write(fd, t, strlen(t)); close(fd); return 1; } int get_fd(char *fname, int mode) { int fd; if(!fname) { fprint(2, "open for read failed : \n"); exits("open failed"); } fd = open(fname, mode); if(fd < 0) { fprint(2, "open for read failed : %s\n", fname); exits("open failed"); } return fd; } void bail(char *msg) { if(msg) fprint(2, msg); exits(msg); } void * emalloc(ulong size) { void* m; m = malloc(size); if(m) return m; exits("out of memory"); return nil; // stop compiler warning } void * emallocz(ulong size) { void* m; m = mallocz(size, 1); if(m) return m; exits("out of memory"); return nil; // stop compiler warning } int read_atoi_from_file(char *file) { int fd; char data[64]; // got more than 64 digits? good luck fd = open(file, OREAD); if(fd < 0) return 0; read(fd, data, 64); close(fd); return atoi(data); } uchar * read_channel_data(char *filename, long datasize) { int fd; uchar *data; long readbytes; data = (uchar*) emalloc(datasize); fd = open(filename, OREAD); if(fd < 0) return nil; readbytes = readn(fd, data, datasize); close(fd); if (readbytes != datasize) { free(data); data = nil; } return data; } char * write_channel_data(char *filename, long datasize, uchar* data) { int fd, written; if(!filename) return "no filename"; fd = open(filename, OWRITE); if(fd < 0) return smprint("write: open failed : %s", filename); written = write(fd, data, datasize); if (written != datasize) return "not all bytes written"; return nil; } uchar * read_channel_rect(char *filename, Rectangle *r) { int fd; uchar *data, *inpoint; long readbytes, datasize; int width, y, dw, dh; if(!filename) return nil; if(!r) return nil; clip_rectangle_to_bitmap(r); dw = r->max.x - r->min.x; dh = r->max.y - r->min.y; datasize = dw * dh; inpoint = data = (uchar*) emalloc(datasize); fd = open(filename, OREAD); if(fd < 0) return nil; width = get_width(); readbytes = 0; for(y = 0; y < dh; y++) { seek(fd, (y + r->min.y) * width + r->min.x, 0); readbytes += readn(fd, inpoint, dw); inpoint = &inpoint[dw]; } close(fd); if (readbytes != datasize) { free(data); data = nil; } return data; } char * write_channel_rect(uchar *dry, uchar *selection, char *filename, Rectangle *dst, uchar *wet, uchar *alpha) { int fd, written, datasize, x, y, width, dw, dh, i, p; float a, s; if(!dst) return "no destination rectangle specified"; if(!filename) return "no filename"; clip_rectangle_to_bitmap(dst); fd = open(filename, OWRITE); if(fd < 0) return smprint("write: open failed : %s", filename); dw = dst->max.x - dst->min.x; dh = dst->max.y - dst->min.y; datasize = dw * dh; written = 0; width = get_width(); if(alpha == nil && selection == nil) { for(y = 0; y < dh; y++) { seek(fd, (y + dst->min.y) * width + dst->min.x, 0); written += write(fd, wet, dw); wet = &wet[dw]; } } else if (selection == nil) { i = 0; for(y = 0; y < dh; y++) { for (x = 0; x < dw; x++) { a = (float)alpha[x] / 255.0 ; wet[x] = a * wet[x] + (1-a) * dry[i]; i++; } seek(fd, (y + dst->min.y) * width + dst->min.x, 0); written += write(fd, wet, dw); wet = &wet[dw]; alpha = &alpha[dw]; } } else if (alpha == nil) { i = 0; for(y = 0; y < dh; y++) { for (x = 0; x < dw; x++) { s = (float)selection[i] / 255.0 ; wet[x] = s * wet[x] + (1-s) * dry[i]; i++; } seek(fd, (y + dst->min.y) * width + dst->min.x, 0); written += write(fd, wet, dw); wet = &wet[dw]; } } else { i = 0; for(y = 0; y < dh; y++) { for (x = 0; x < dw; x++) { s = (float)selection[i] / 255.0 ; a = (float)alpha[i] / 255.0 ; p = s * a * wet[x] + (1- a * s) * dry[i]; wet[x] = (uchar)p; i++; } seek(fd, (y + dst->min.y) * width + dst->min.x, 0); written += write(fd, wet, dw); wet = &wet[dw]; } } close(fd); if (written != datasize) return "not all bytes written"; return nil; } void clip_rectangle_to_bitmap(Rectangle *r) { int m; if(!r) return; r->min.x = max_int(0, r->min.x); r->min.y = max_int(0, r->min.y); m = get_width() ; r->max.x = min_int(r->max.x, m); m = get_height(); r->max.y = min_int(r->max.y, m); r->min.x = min_int(r->min.x, r->max.x); r->max.x = max_int(r->max.x, r->min.x); r->min.y = min_int(r->min.y, r->max.y); r->max.y = max_int(r->max.y, r->min.y); } Rectangle* rectangle_from_txt(char *txt) { char *args[4]; Rectangle *r=nil; if(!txt) return nil; if(getfields(txt, args, 4, 1, ".,-to") == 4) { r = (Rectangle*) emalloc(sizeof(Rectangle)); r->min.x = atoi(args[0]); r->min.y = atoi(args[1]); r->max.x = atoi(args[2]); r->max.y = atoi(args[3]); } return r; } uchar get_pixel(uchar *data, int width, int height, float x, float y, int wrap_type) { int a,b,c,d; int fx, fy, cx, cy, fwy, cwy; float dax, day, dbx, dby, dcx, dcy, ddx, ddy; long lx, ly; //print("x %0.2f\n", x); //print("y %0.2f\n", y); switch(wrap_type) { case 2 : # 0-max-max-0 i.e. mirrored lx = (long) floor(x / width); ly = (long) floor(y / height); if (lx % 2 == 1) x = -x; if (ly % 2 == 1) y = - y; case 1 : # 0-max-0-max i,e, wrap around while (x >= width) { x -= fabs(floor(x / width)) * width; } while (x < 0) { x += fabs(floor(x / width)) * width; } while (y >= height) { y -= fabs(floor(y / height)) * height; } while (y < 0) { y += fabs(floor(y / height) )* height; } break; } fx = x; cx = fx + 1; fy = y; cy = fy + 1; cy = min_int(cy, height - 1); fy = min_int(fy, height - 1); cx = min_int(cx, width - 1); fx = min_int(fx, width - 1); cy = max_int(cy, 0); fy = max_int(fy, 0); cx = max_int(cx, 0); fx = max_int(fx, 0); dcx = dax = cx - x; dbx = ddx = 1 - dax; dby = day = cy - y; dcy = ddy = 1 - dby; fwy = width * fy; cwy = width * cy; a = data[fwy + fx]; b = data[fwy + cx]; c = data[cwy + fx]; d = data[cwy + cx]; return dax * day * a + dbx * dby * b + dcx * dcy * c + ddx * ddy * d; } // ifslib.c int min_int(int a, int b); int max_int(int a, int b); void bail(char *msg); void *emallocz(ulong sz); void *emalloc(ulong sz); int get_fd(char *fname, int mode); int read_atoi_from_file(char *file); int write_int_to_file(char *filename, int i) ; uchar *read_channel_data(char *filename, long datasize); char *write_channel_data(char *filename, long datasize, uchar* data); int get_width(void); int get_height(void); int set_width(int w); int set_height(int h); uchar * read_channel_rect(char *filename, Rectangle *r) ; char *write_channel_rect(uchar *dry, uchar *selection, char *filename, Rectangle *dst, uchar *wet, uchar *alpha); void clip_rectangle_to_bitmap(Rectangle *r) ; Rectangle * rectangle_from_txt(char *txt); uchar get_pixel(uchar *data, int width, int height, float x, float y, int wrap); #include #include #include #include #include #include #include <9p.h> #include #include "ifslib.h" #include "import_ppm.h" #include "imgfp.h" enum { id_images_folder=0x01, id_new=0x02, id_imgfolder=0x03, id_width=0x04, id_height=0x05, id_ppm=0x06, id_ctrl=0x07, id_alpha=0x0100, id_select=0x0101, id_red=0x0200, id_green=0x0201, id_blue=0x0202, id_cyan=0x0300, id_magenta=0x0301, id_yellow=0x0302, id_black=0x0303, id_hue=0x0400, id_saturation=0x0401, id_lightness=0x0402, id_grey=0x0500, }; typedef struct Floatmap Floatmap; typedef struct Mapbook Mapbook; typedef struct Aux Aux; File * create_new_file(File *dir, char* filename, int perm, int id_code, Mapbook *bitmap); Aux * new_aux(int id, Mapbook *b); Tree *tree=nil; File *images_folder=nil; Aux *aux_list=nil; int aux_count=0; int mapbook_count=0; QLock aux_lock; struct Aux { int index; int id; Mapbook *mapbook; Aux *next; }; struct Floatmap { int id; QLock lock; char *name; float *data; Floatmap *next; }; struct Mapbook { int width; int height; int index; QLock lock; Floatmap *floatmaps; }; Mapbook * new_mapbook(int width, int height) { Mapbook *m; m = (Mapbook*) emallocz(sizeof(Mapbook)); m->width = width; m->height = height; return m; } Mapbook * free_mapbook(Mapbook *m) { // always suicides Floatmap *f, *next; if(m) { for(f = m->floatmaps; f; f = next) { next = f->next; // free(f->data); // free(f); } // free(m); } return nil; } void print_mapbook(Mapbook *m) { print("width %d\nheight %d\n", m->width, m->height); Floatmap *f; for(f = m->floatmaps; f; f = f->next) { print("channel %d %s\n", f->id, f->name); } } Floatmap * get_floatmap(Mapbook *m, int id) { Floatmap *f; if(!m) return nil; qlock(&m->lock); for(f = m->floatmaps; f; f=f->next) if (f->id == id) break; qunlock(&m->lock); return f; } Floatmap * get_or_create_floatmap(Mapbook *m, int id) { Floatmap *found, *last = nil; qlock(&m->lock); for(found = m->floatmaps; found; found = found->next) { last = found; if(found->id == id) break; } if(!found) { found = (Floatmap*)emallocz(sizeof(Floatmap)); last ? (last->next = found) : (m->floatmaps = found); found->id = id; found->data = (float*) emallocz(sizeof(float) * m->width * m->height); } qunlock(&m->lock); return found; } File * create_new_file(File *dir, char* filename, int perm, int id_code, Mapbook *m) { File *file; Aux *a; if (dir == nil || filename == nil) return nil; incref(dir); /* so walk doesn't kill it immediately on failure */ file = walkfile(dir, filename); if (file) { file = nil; } else { a = new_aux(id_code, m); file = createfile(dir, filename, getuser(), perm, &a->index); incref(dir); } decref(dir); return file; } void add_channels(File* dir, Mapbook* m) { create_new_file(dir, "ctrl", 0666, id_ctrl, m); create_new_file(dir, "width", 0666, id_width, m); create_new_file(dir, "height", 0666, id_height, m); /* create_new_file(dir, "ppm", 0444, id_ppm, m); create_new_file(dir, "red", 0666, id_red, m); create_new_file(dir, "green", 0666, id_green, m); create_new_file(dir, "blue", 0666, id_blue, m); create_new_file(dir, "select", 0666, id_select, m); create_new_file(dir, "alpha", 0666, id_alpha, m); // as yet unused but present for when required // nothing to stop them being used create_new_file(dir, "cyan", 0666, id_cyan, m); create_new_file(dir, "magenta", 0666, id_magenta, m); create_new_file(dir, "yellow", 0666, id_yellow, m); create_new_file(dir, "black", 0666, id_black, m); create_new_file(dir, "hue", 0666, id_cyan, m); create_new_file(dir, "saturation", 0666, id_magenta, m); create_new_file(dir, "lightness", 0666, id_yellow, m); */ } Aux * create_new_image_folder(char *filename) { Aux *a; File *file = walkfile(images_folder, filename); if (file) return nil; a = new_aux(id_imgfolder, nil); file = createfile(images_folder, filename, getuser(), DMDIR|0555, &a->index); incref(images_folder); add_channels(file, a->mapbook); return a; } Aux * get_aux(void *indexp) { Aux *a; int index = *(int*)indexp; qlock(&aux_lock); for(a = aux_list; a; a = a->next) if (a->index == index) break; qunlock(&aux_lock); return a; } Aux * new_aux(int id, Mapbook *m) { Aux *a; qlock(&aux_lock); if (m == nil) { m = (Mapbook*) emallocz(sizeof(Mapbook)); m->index = mapbook_count++; } if(aux_list == nil) { aux_list = (Aux*) emallocz (sizeof(Aux)); aux_list->index = aux_count++; aux_list->id = id; aux_list->mapbook = m; qunlock(&aux_lock); return aux_list; } a = aux_list; while(a->next) a = a->next; a->next = (Aux*) emallocz (sizeof(Aux)); a->next->id = id; a->next->index = aux_count++; a->next->mapbook = m; qunlock(&aux_lock); return a->next; }; void free_aux(Aux *a) { a->mapbook = free_mapbook(a->mapbook); } void fill_floatmap_from_int(int pixels, float *f, int maxv, int *data) { int i; if(f && data) for(i = 0; i < pixels; i++) f[i] = (float)data[i] / (float)maxv; } void set_channel_from_int(File *dir, char *name, int pixels, int maxv, int *data) { File *channel; Floatmap *f; Aux *aux; incref(dir); channel = walkfile(dir, name); if(!channel) { aux = get_aux(dir->aux); aux = new_aux(id_red, aux->mapbook); f = get_or_create_floatmap(aux->mapbook, aux->id); fill_floatmap_from_int(pixels, f->data, maxv, data); channel = createfile(dir, name, dir->uid, DMDIR|0500, &aux->id); } if(channel) decref(channel); } char * import_ppm(File *dir, char *fname) { RGBint *rgb = nil; Biobuf b; int pixels = 0; int fd = open(fname, OREAD); if(fd == -1) return nil; if(Binit(&b, fd, OREAD) != -1) { rgb = readppm(&b); Bterm(&b); if(rgb) { pixels = rgb->width * rgb->height; set_channel_from_int(dir, "red", pixels, rgb->maxcol, rgb->r); set_channel_from_int(dir, "green", pixels, rgb->maxcol, rgb->g); set_channel_from_int(dir, "blue", pixels, rgb->maxcol, rgb->b); } } close(fd); rgb = free_rgb(rgb); return nil; } char * process_ctl_message(Aux *aux, Req *r) { int t; char *tokens[6]; t = tokenize(r->ifcall.data, tokens, 6); switch(t) { case 3: case 4 : if(strcmp("import", tokens[0]) == 0) { if(strcmp("ppm", tokens[1]) == 0) { return import_ppm(r->fid->file->parent, tokens[2]); } } break; } if(!(aux && aux->mapbook)) return nil; if (aux->mapbook) { } return nil; } char * set_mapbook_width(Mapbook *m, int nw) { Rectangle src, dst; Floatmap *original; float *data, *inpoint, *srcpoint; int y, dw; if(!m) return "mapbook nil"; src.max.x = m->width; dst.max.x = nw; src.max.y = dst.max.y = m->height; dw = nw < m->width ? nw : m->width; original = m->floatmaps; if(!original) { m->width = nw; return nil; } while(original) { if(original->data) { inpoint = data = (float*) emallocz(sizeof(float)*dst.max.x * dst.max.y); srcpoint = original->data; for(y = 0; y < m->height; y++) { memcpy(inpoint, srcpoint, sizeof(float)*dw); inpoint = &inpoint[nw]; srcpoint = &srcpoint[m->width]; } free(original->data); original->data = data; } original = original->next; } m->width = nw; return nil; } char * set_mapbook_height(Mapbook *m, int nh) { Floatmap *original; float *data; if(!m) return "mapbook nil"; original = m->floatmaps; if(!original) { m->height = nh; return nil; } while(original) { if(original->data) { data = (float*) emallocz(sizeof(float)*nh * m->width); memcpy(data, original->data, sizeof(float)*nh * m->width); free(original->data); original->data = data; } original = original->next; } m->height = nh; return nil; } void fswrite(Req *r) { Aux *aux ; Floatmap *target; char *errstr = nil; char *txt; vlong dataend; aux = get_aux(r->fid->file->aux); if(aux== nil) { respond(nil, "not found"); return; } if(aux->id & 0xFF00) { // it's a channel target = get_or_create_floatmap(aux->mapbook, aux->id); dataend = aux->mapbook->width * aux->mapbook->height; if ((r->ifcall.offset + r->ifcall.count) > dataend) { respond(r, "too much data"); return; } // is this locking even necessary ? qlock(&target->lock); memcpy(&target->data[r->ifcall.offset], r->ifcall.data, r->ifcall.count); qunlock(&target->lock); r->ofcall.count = r->ifcall.count; respond(r, nil); return; } switch(aux->id) { case id_new : if (r->ifcall.count > 0) { txt = (char*)emallocz(r->ifcall.count+1); memcpy(txt, r->ifcall.data, r->ifcall.count); txt[strcspn(txt, "\n/\0 ")] = 0; if(create_new_image_folder(txt)) r->ofcall.count = r->ifcall.count; else errstr = smprint("create failed - file existed"); } break; case id_width : errstr = set_mapbook_width(aux->mapbook, atoi(r->ifcall.data)); break; case id_height : errstr = set_mapbook_height(aux->mapbook, atoi(r->ifcall.data)); break; case id_ctrl : errstr = process_ctl_message(aux, r); break; } respond(r, errstr); free(errstr); } void fill_ofcall_with_data(Fcall *ifcall, Fcall *ofcall, int datasize, char *data) { if (ifcall->offset < datasize) { if((ifcall->offset + ifcall->count) < datasize) { ofcall->data = data + ifcall->offset; ofcall->count = ifcall->count; } else { ofcall->data = data + ifcall->offset; ofcall->count = datasize - ifcall->offset; } } else { ofcall->data = nil; ofcall->count = 0; } } void fill_ofcall_with_floatmap(Fcall *ifcall, Fcall *ofcall, Mapbook *m, int id) { Floatmap *f; long pixels; if(f = get_floatmap(m, id)) { pixels = sizeof(float) * m->width * m->height; fill_ofcall_with_data(ifcall, ofcall, pixels, (char*) f->data); } else { ofcall->data = nil; ofcall->count = 0; } } char * ppm_header(Mapbook *m) { return smprint("P6 %06d %06d 255\n", m->width, m->height); } long ppm_size(char *header, Mapbook *m) { return strlen(header) + 3 * m->width * m->height; } char * fill_ofcall_with_ppm(Fcall *ifcall, Fcall *ofcall, Mapbook *m) { char *header; int header_size; long ppmsize, limit, req_length, start, pixel, end_pixel; char *insert_point; Floatmap *r, *g, *b; ofcall->data = nil; ofcall->count = 0; if(!m) return ofcall->data; header = ppm_header(m); header_size = strlen(header); ppmsize = ppm_size(header, m); if(ifcall->offset < ppmsize) { r = get_floatmap(m, id_red); g = get_floatmap(m, id_green); b = get_floatmap(m, id_blue); req_length = ifcall->offset + ifcall->count; limit = (req_length < ppmsize) ? req_length : ppmsize; req_length = limit - ifcall->offset; insert_point = ofcall->data = (char*) emallocz(req_length); start = ifcall->offset; if(start < header_size) { ofcall->count = header_size - start; if (ofcall->count > ifcall->count) ofcall->count = ifcall->count; memcpy(insert_point, &header[start], ofcall->count); insert_point = &ofcall->data[ofcall->count]; } else ofcall->count = 0; if(ofcall->count == ifcall->count) return ofcall->data; req_length -= ofcall->count; start = ifcall->offset + ofcall->count - header_size; pixel = start / 3; /* reads always finish on a pixel boundary so that the next read starts at a pixel boundary though I have no proof that it *always* works this switch was supposed deal with the boundaries but it was always unused so I commented it out switch(start % 3) { case 1 : insert_point[0] = r->data[pixel-1]; insert_point = &insert_point[1]; ofcall->count++; req_length--; if (req_length == 0) return ofcall->data; case 2: insert_point[0] = b->data[pixel-1]; insert_point = &insert_point[1]; ofcall->count++; req_length--; if (req_length == 0) return ofcall->data; } */ end_pixel = pixel + req_length / 3; for(; pixel < end_pixel; pixel++) { insert_point[0] = r->data[pixel]; ofcall->count++; req_length--; if (req_length == 0) return ofcall->data; insert_point[1] = g->data[pixel]; ofcall->count++; req_length--; if (req_length == 0) return ofcall->data; insert_point[2] = b->data[pixel]; ofcall->count++; req_length--; if (req_length == 0) return ofcall->data; insert_point = &insert_point[3]; } // reads always finish on a pixel boundary so that the next read starts at a pixel boundary // similarly there was another switch here, it was wrong so I deleted it } return ofcall->data; } void fsread(Req *r) { Aux *aux; char *data=nil; aux = get_aux(r->fid->file->aux); if(!aux) { respond(r, "not found"); return; } switch(aux->id){ case id_width : data = smprint("%d", aux->mapbook->width); readstr(r, data); break; case id_height : data = smprint("%d", aux->mapbook->height); readstr(r, data); break; case id_ppm : data = fill_ofcall_with_ppm(&r->ifcall, &r->ofcall, aux->mapbook); break; default : if(aux->id & 0xFF00) // it's a channel fill_ofcall_with_floatmap(&r->ifcall, &r->ofcall, aux->mapbook, aux->id); } respond(r, nil); free(data); } void fsend (Srv *) { Aux *aux, *next; for(aux = aux_list; aux; aux = next) { next = aux->next; free_aux(aux); } aux_list = nil; } void fstati(Req *r) { Aux *a = get_aux(r->fid->file->aux); char *data; if(a) switch(a->id) { case id_width : data = smprint("%d", a->mapbook->width); r->d.length = strlen(data); free(data); break; case id_height : data = smprint("%d", a->mapbook->height); r->d.length = strlen(data); free(data); break; case id_ppm : data = ppm_header(a->mapbook); r->d.length = ppm_size(data, a->mapbook); free(data); break; default : if(a->id & 0xFF00) { // it's a channel Mapbook *m = (Mapbook*) (a->mapbook); if(m) { if(get_floatmap(m, a->id)) { r->d.length = m->width * m->height; } } } break; } respond(r, nil); } Srv fs = { .read= fsread, .write= fswrite, .end= fsend, .stat= fstati, }; static void usage(void) { fprint(2, "usage: imgfs [-n mtpt] \n"); exits("usage"); } void main(int argc, char **argv) { char *mtpt; mtpt = "/n/imgfp"; ARGBEGIN{ case 'n': mtpt = ARGF(); break; }ARGEND; if(argc != 0) usage(); tree = fs.tree = alloctree(getuser(), getuser(), DMDIR|0555, nil); create_new_file(tree->root, "new", 0666, id_new, nil); images_folder = create_new_file(tree->root, "images", DMDIR|0777, id_images_folder, nil); postmountsrv(&fs, nil, mtpt, MREPL); exits(nil); } /* Put mk install imgfs/imgfs cd /n/imgfs echo arab > new cd images/arab imgfs/import_ppm /usr/maht/imgfs/arabian.ppm ls -l * wc ppm */ typedef struct Bitmap Bitmap;#include #include #include #include #include #include #include <9p.h> #include #include "ifslib.h" enum { id_images_folder=0x01, id_new=0x02, id_imgfolder=0x03, id_width=0x04, id_height=0x05, id_ppm=0x06, id_alpha=0x0100, id_select=0x0101, id_red=0x0200, id_green=0x0201, id_blue=0x0202, id_cyan=0x0300, id_magenta=0x0301, id_yellow=0x0302, id_black=0x0303, id_hue=0x0400, id_saturation=0x0401, id_lightness=0x0402, id_grey=0x0500, }; typedef struct Bitmap Bitmap; typedef struct Mapbook Mapbook; typedef struct Aux Aux; File * create_new_file(File *dir, char* filename, int perm, int id_code, Mapbook *bitmap); Aux * new_aux(int id, Mapbook *b); Tree *tree=nil; File *images_folder=nil; Aux *aux_list=nil; int aux_count=0; int mapbook_count=0; QLock aux_lock; struct Aux { int index; int id; Mapbook *mapbook; Aux *next; }; struct Mapbook { int width; int height; int index; QLock lock; Bitmap *bitmaps; }; struct Bitmap { int id; QLock lock; char *name; uchar *data; Bitmap *next; }; Mapbook * new_mapbook(int width, int height) { Mapbook *m; m = (Mapbook*) emallocz(sizeof(Mapbook)); m->width = width; m->height = height; return m; } Mapbook * free_mapbook(Mapbook *m) { // always suicides Bitmap *b, *next; if(m) { for(b = m->bitmaps; b; b = next) { next = b->next; // free(b->data); // free(b); } // free(m); } return nil; } void print_mapbook(Mapbook *m) { print("width %d\nheight %d\n", m->width, m->height); Bitmap *b; for(b = m->bitmaps; b; b = b->next) { print("channel %d %s\n", b->id, b->name); } } Bitmap * get_bitmap(Mapbook *m, int id) { Bitmap *b; if(!m) return nil; qlock(&m->lock); for(b = m->bitmaps; b; b=b->next) if (b->id == id) break; qunlock(&m->lock); return b; } Bitmap * get_or_create_bitmap(Mapbook *m, int id) { Bitmap *found, *last = nil; qlock(&m->lock); for(found = m->bitmaps; found; found = found->next) { last = found; if(found->id == id) break; } if(!found) { found = (Bitmap*)emallocz(sizeof(Bitmap)); last ? (last->next = found) : (m->bitmaps = found); found->id = id; found->data = (uchar*) emallocz(m->width * m->height); } qunlock(&m->lock); return found; } File * create_new_file(File *dir, char* filename, int perm, int id_code, Mapbook *m) { File *file; Aux *a; if (dir == nil || filename == nil) return nil; incref(dir); /* so walk doesn't kill it immediately on failure */ file = walkfile(dir, filename); if (file) { file = nil; } else { a = new_aux(id_code, m); file = createfile(dir, filename, getuser(), perm, &a->index); incref(dir); } decref(dir); return file; } void add_channels(File* dir, Mapbook* m) { create_new_file(dir, "ppm", 0444, id_ppm, m); create_new_file(dir, "width", 0666, id_width, m); create_new_file(dir, "height", 0666, id_height, m); create_new_file(dir, "red", 0666, id_red, m); create_new_file(dir, "green", 0666, id_green, m); create_new_file(dir, "blue", 0666, id_blue, m); create_new_file(dir, "select", 0666, id_select, m); create_new_file(dir, "alpha", 0666, id_alpha, m); // as yet unused but present for when required // nothing to stop them being used /* create_new_file(dir, "cyan", 0666, id_cyan, m); create_new_file(dir, "magenta", 0666, id_magenta, m); create_new_file(dir, "yellow", 0666, id_yellow, m); create_new_file(dir, "black", 0666, id_black, m); create_new_file(dir, "hue", 0666, id_cyan, m); create_new_file(dir, "saturation", 0666, id_magenta, m); create_new_file(dir, "lightness", 0666, id_yellow, m); */ } Aux * create_new_image_folder(char *filename) { Aux *a; File *file = walkfile(images_folder, filename); if (file) return nil; a = new_aux(id_imgfolder, nil); file = createfile(images_folder, filename, getuser(), DMDIR|0555, &a->index); incref(images_folder); add_channels(file, a->mapbook); return a; } Aux * get_aux(void *indexp) { Aux *a; int index = *(int*)indexp; qlock(&aux_lock); for(a = aux_list; a; a = a->next) if (a->index == index) break; qunlock(&aux_lock); return a; } Aux * new_aux(int id, Mapbook *m) { Aux *a; qlock(&aux_lock); if (m == nil) { m = (Mapbook*) emallocz(sizeof(Mapbook)); m->index = mapbook_count++; } if(aux_list == nil) { aux_list = (Aux*) emallocz (sizeof(Aux)); aux_list->index = aux_count++; aux_list->id = id; aux_list->mapbook = m; qunlock(&aux_lock); return aux_list; } a = aux_list; while(a->next) a = a->next; a->next = (Aux*) emallocz (sizeof(Aux)); a->next->id = id; a->next->index = aux_count++; a->next->mapbook = m; qunlock(&aux_lock); return a->next; }; void free_aux(Aux *a) { a->mapbook = free_mapbook(a->mapbook); } char * process_ctl_message(Aux *aux) { if(!(aux && aux->mapbook)) return nil; if (aux->mapbook) { } return nil; } char * set_mapbook_width(Mapbook *m, int nw) { Rectangle src, dst; Bitmap *original; uchar *data, *inpoint, *srcpoint; int y, dw; if(!m) return "mapbook nil"; src.max.x = m->width; dst.max.x = nw; src.max.y = dst.max.y = m->height; dw = nw < m->width ? nw : m->width; original = m->bitmaps; if(!original) { m->width = nw; return nil; } while(original) { if(original->data) { inpoint = data = (uchar*) emallocz(dst.max.x * dst.max.y); srcpoint = original->data; for(y = 0; y < m->height; y++) { memcpy(inpoint, srcpoint, dw); inpoint = &inpoint[nw]; srcpoint = &srcpoint[m->width]; } free(original->data); original->data = data; } original = original->next; } m->width = nw; return nil; } char * set_mapbook_height(Mapbook *m, int nh) { Bitmap *original; uchar *data; if(!m) return "mapbook nil"; original = m->bitmaps; if(!original) { m->height = nh; return nil; } while(original) { if(original->data) { data = (uchar*) emallocz(nh * m->width); memcpy(data, original->data, nh * m->width); free(original->data); original->data = data; } original = original->next; } m->height = nh; return nil; } void fswrite(Req *r) { Aux *aux ; Bitmap *target; char *errstr = nil; char *txt; vlong dataend; aux = get_aux(r->fid->file->aux); if(aux== nil) { respond(nil, "not found"); return; } if(aux->id & 0xFF00) { // it's a channel target = get_or_create_bitmap(aux->mapbook, aux->id); dataend = aux->mapbook->width * aux->mapbook->height; if ((r->ifcall.offset + r->ifcall.count) > dataend) { respond(r, "too much data"); return; } // is this locking even necessary ? qlock(&target->lock); memcpy(&target->data[r->ifcall.offset], r->ifcall.data, r->ifcall.count); qunlock(&target->lock); r->ofcall.count = r->ifcall.count; respond(r, nil); return; } switch(aux->id) { case id_new : if (r->ifcall.count > 0) { txt = (char*)emallocz(r->ifcall.count+1); memcpy(txt, r->ifcall.data, r->ifcall.count); txt[strcspn(txt, "\n/\0 ")] = 0; if(create_new_image_folder(txt)) r->ofcall.count = r->ifcall.count; else errstr = smprint("create failed - file existed"); } break; case id_width : errstr = set_mapbook_width(aux->mapbook, atoi(r->ifcall.data)); break; case id_height : errstr = set_mapbook_height(aux->mapbook, atoi(r->ifcall.data)); break; } respond(r, errstr); free(errstr); } void fill_ofcall_with_data(Fcall *ifcall, Fcall *ofcall, int datasize, char *data) { if (ifcall->offset < datasize) { if((ifcall->offset + ifcall->count) < datasize) { ofcall->data = data + ifcall->offset; ofcall->count = ifcall->count; } else { ofcall->data = data + ifcall->offset; ofcall->count = datasize - ifcall->offset; } } else { ofcall->data = nil; ofcall->count = 0; } } void fill_ofcall_with_bitmap(Fcall *ifcall, Fcall *ofcall, Mapbook *m, int id) { Bitmap *b; long pixels; if(b = get_bitmap(m, id)) { pixels = m->width * m->height; fill_ofcall_with_data(ifcall, ofcall, pixels, (char*) b->data); } else { ofcall->data = nil; ofcall->count = 0; } } char * ppm_header(Mapbook *m) { return smprint("P6 %06d %06d 255\n", m->width, m->height); } long ppm_size(char *header, Mapbook *m) { return strlen(header) + 3 * m->width * m->height; } char * fill_ofcall_with_ppm(Fcall *ifcall, Fcall *ofcall, Mapbook *m) { char *header; int header_size; long ppmsize, limit, req_length, start, pixel, end_pixel; char *insert_point; Bitmap *r, *g, *b; ofcall->data = nil; ofcall->count = 0; if(!m) return ofcall->data; header = ppm_header(m); header_size = strlen(header); ppmsize = ppm_size(header, m); if(ifcall->offset < ppmsize) { r = get_bitmap(m, id_red); g = get_bitmap(m, id_green); b = get_bitmap(m, id_blue); req_length = ifcall->offset + ifcall->count; limit = (req_length < ppmsize) ? req_length : ppmsize; req_length = limit - ifcall->offset; insert_point = ofcall->data = (char*) emallocz(req_length); start = ifcall->offset; if(start < header_size) { ofcall->count = header_size - start; if (ofcall->count > ifcall->count) ofcall->count = ifcall->count; memcpy(insert_point, &header[start], ofcall->count); insert_point = &ofcall->data[ofcall->count]; } else ofcall->count = 0; if(ofcall->count == ifcall->count) return ofcall->data; req_length -= ofcall->count; start = ifcall->offset + ofcall->count - header_size; pixel = start / 3; /* reads always finish on a pixel boundary so that the next read starts at a pixel boundary though I have no proof that it *always* works this switch was supposed deal with the boundaries but it was always unused so I commented it out switch(start % 3) { case 1 : insert_point[0] = r->data[pixel-1]; insert_point = &insert_point[1]; ofcall->count++; req_length--; if (req_length == 0) return ofcall->data; case 2: insert_point[0] = b->data[pixel-1]; insert_point = &insert_point[1]; ofcall->count++; req_length--; if (req_length == 0) return ofcall->data; } */ end_pixel = pixel + req_length / 3; for(; pixel < end_pixel; pixel++) { insert_point[0] = r->data[pixel]; ofcall->count++; req_length--; if (req_length == 0) return ofcall->data; insert_point[1] = g->data[pixel]; ofcall->count++; req_length--; if (req_length == 0) return ofcall->data; insert_point[2] = b->data[pixel]; ofcall->count++; req_length--; if (req_length == 0) return ofcall->data; insert_point = &insert_point[3]; } // reads always finish on a pixel boundary so that the next read starts at a pixel boundary // similarly there was another switch here, it was wrong so I deleted it } return ofcall->data; } void fsread(Req *r) { Aux *aux; char *data=nil; aux = get_aux(r->fid->file->aux); if(!aux) { respond(r, "not found"); return; } switch(aux->id){ case id_width : data = smprint("%d", aux->mapbook->width); readstr(r, data); break; case id_height : data = smprint("%d", aux->mapbook->height); readstr(r, data); break; case id_ppm : data = fill_ofcall_with_ppm(&r->ifcall, &r->ofcall, aux->mapbook); break; default : if(aux->id & 0xFF00) // it's a channel fill_ofcall_with_bitmap(&r->ifcall, &r->ofcall, aux->mapbook, aux->id); } respond(r, nil); free(data); } void fsend (Srv *) { Aux *aux, *next; for(aux = aux_list; aux; aux = next) { next = aux->next; free_aux(aux); } aux_list = nil; } void fstati(Req *r) { Aux *a = get_aux(r->fid->file->aux); char *data; if(a) switch(a->id) { case id_width : data = smprint("%d", a->mapbook->width); r->d.length = strlen(data); free(data); break; case id_height : data = smprint("%d", a->mapbook->height); r->d.length = strlen(data); free(data); break; case id_ppm : data = ppm_header(a->mapbook); r->d.length = ppm_size(data, a->mapbook); free(data); break; default : if(a->id & 0xFF00) { // it's a channel Mapbook *m = (Mapbook*) (a->mapbook); if(m) { if(get_bitmap(m, a->id)) { r->d.length = m->width * m->height; } } } break; } respond(r, nil); } Srv fs = { .read= fsread, .write= fswrite, .end= fsend, .stat= fstati, }; static void usage(void) { fprint(2, "usage: imgfs [-n mtpt] \n"); exits("usage"); } void main(int argc, char **argv) { char *mtpt; mtpt = "/n/imgfs"; ARGBEGIN{ case 'n': mtpt = ARGF(); break; }ARGEND; if(argc != 0) usage(); tree = fs.tree = alloctree(getuser(), getuser(), DMDIR|0555, nil); create_new_file(tree->root, "new", 0666, id_new, nil); images_folder = create_new_file(tree->root, "images", DMDIR|0777, id_images_folder, nil); postmountsrv(&fs, nil, mtpt, MREPL); exits(nil); } /* Put mk install imgfs/imgfs cd /n/imgfs echo arab > new cd images/arab imgfs/import_ppm /usr/maht/imgfs/arabian.ppm ls -l * wc ppm */#include #include #include #include #include #include "ifslib.h" static int bitc, nbit; int grey_fd; int m8_fd; /* * fetch a non-comment character. */ static int Bgetch(Biobufhdr *b) { int c; for(;;) { c = Bgetc(b); if(c == '#') { while((c = Bgetc(b)) != Beof && c != '\n') ; } return c; } } /* * fetch a nonnegative decimal integer. */ static int Bgetint(Biobufhdr *b) { int c; int i; while((c = Bgetch(b)) != Beof && !isdigit(c)) ; if(c == Beof) return -1; i = 0; do { i = i*10 + (c-'0'); } while((c = Bgetch(b)) != Beof && isdigit(c)); return i; } static int Bgetdecimalbit(Biobufhdr *b) { int c; while((c = Bgetch(b)) != Beof && c != '0' && c != '1') ; if(c == Beof) return -1; return c == '1'; } static int Bgetbit(Biobufhdr *b) { if(nbit == 0) { nbit = 8; bitc = Bgetc(b); if(bitc == -1) return -1; } nbit--; return (bitc >> (nbit-1)) & 0x1; } static void Bflushbit(Biobufhdr*) { nbit = 0; } void main(int argc, char **argv) { char *errstr = nil; Biobuf b; char *chan; Rectangle r; int width, height; if(argc > 2) bail("usage : import_m8 [filename]"); m8_fd = 0; if(argv[1]) m8_fd = get_fd(argv[1], OREAD); Binit(&b, m8_fd, OREAD); chan = (char*) malloc(12); Bread(&b, chan, 12); chan[11] = 0; if(strcmp(chan, " m8") != 0) bail ("sorry m8 files only"); r.min.x = Bgetint(&b); r.min.y = Bgetint(&b); r.max.x = Bgetint(&b); r.max.y = Bgetint(&b); width = r.max.x - r.min.x; height = r.max.y - r.min.y; if(width > 0 && height > 0) { print("hey\n"); } close(m8_fd); bail(errstr); } #include #include #include #include #include #include "ifslib.h" #include "import_ppm.h" int ppm_fd, red_fd, green_fd, blue_fd; int magic, width, height, maxval; float scalar; enum { /* Channel descriptors */ CRGB = 0, /* three channels, no map */ CYCbCr = 1, /* three channels, no map, level-shifted 601 color space */ CY = 2, /* one channel, luminance */ CRGB1 = 3, /* one channel, map present */ CRGBV = 4, /* one channel, map is RGBV, understood */ CRGB24 = 5, /* one channel in correct data order for loadimage(RGB24) */ CRGBA32 = 6, /* one channel in correct data order for loadimage(RGBA32) */ CYA16 = 7, /* one channel in correct data order for loadimage(Grey8+Alpha8) */ CRGBVA16= 8, /* one channel in correct data order for loadimage(CMAP8+Alpha8) */ /* GIF flags */ TRANSP = 1, INPUT = 2, DISPMASK = 7<<2 }; static int bitc, nbit; /* * fetch a non-comment character. */ static int Bgetch(Biobufhdr *b) { int c; for(;;) { c = Bgetc(b); if(c == '#') { while((c = Bgetc(b)) != Beof && c != '\n') ; } return c; } } /* * fetch a nonnegative decimal integer. */ static int Bgetint(Biobufhdr *b) { int c; int i; while((c = Bgetch(b)) != Beof && !isdigit(c)) ; if(c == Beof) return -1; i = 0; do { i = i*10 + (c-'0'); } while((c = Bgetch(b)) != Beof && isdigit(c)); return i; } static int Bgetdecimalbit(Biobufhdr *b) { int c; while((c = Bgetch(b)) != Beof && c != '0' && c != '1') ; if(c == Beof) return -1; return c == '1'; } static int Bgetbit(Biobufhdr *b) { if(nbit == 0) { nbit = 8; bitc = Bgetc(b); if(bitc == -1) return -1; } nbit--; return (bitc >> (nbit-1)) & 0x1; } static void Bflushbit(Biobufhdr*) { nbit = 0; } typedef struct Pix Pix; struct Pix { char magic; int maxcol; int (*fetch)(Biobufhdr*); int nchan; int chandesc; int invert; void (*flush)(Biobufhdr*); }; static Pix pix[] = { { '1', 1, Bgetdecimalbit, 1, CY, 1, nil }, /* portable bitmap */ { '4', 1, Bgetbit, 1, CY, 1, Bflushbit }, /* raw portable bitmap */ { '2', 0, Bgetint, 1, CY, 0, nil }, /* portable greymap */ { '5', 0, Bgetc, 1, CY, 0, nil }, /* raw portable greymap */ { '3', 0, Bgetint, 3, CRGB, 0, nil }, /* portable pixmap */ { '6', 0, Bgetc, 3, CRGB, 0, nil }, /* raw portable pixmap */ { 0 }, }; RGBint * free_rgb(RGBint *rgb) { if(rgb) { free(rgb->r); free(rgb->g); free(rgb->b); } return nil; } RGBint * readppm(Biobuf *b) { RGBint *rgb; int i, ch, r, c, fd; int (*fetch)(Biobufhdr*); char *e; Pix *p; int pixels; e = "bad file format"; if(Bgetc(b) != 'P') { fprint(2, "Doubt it's a ppm"); return nil; } c = Bgetc(b); for(p=pix; p->magic; p++) if(p->magic == c) break; if(p->magic == 0) { fprint(2, "Bad magic"); return nil; } if(c != '3' && c != '6') { fprint(2, "sorry, RGB only"); return nil; } rgb = (RGBint*)emallocz(sizeof(RGBint)); rgb->width = Bgetint(b); rgb->height = Bgetint(b); if(rgb->width <= 0 || rgb->height <= 0){ fprint(2, "width or height < 0"); free_rgb(rgb); return nil; } rgb->maxcol = p->maxcol; if(rgb->maxcol == 0) { rgb->maxcol = Bgetint(b); if(rgb->maxcol <= 0) { fprint(2, "rgb->maxcol <= 0"); free_rgb(rgb); return nil; } } pixels = rgb->width * rgb->height; rgb->r = (int*)emallocz(sizeof(int)*pixels); rgb->g = (int*)emallocz(sizeof(int)*pixels); rgb->b = (int*)emallocz(sizeof(int)*pixels); fetch = p->fetch; for(i=0; rgb && i < pixels; i++) if(((rgb->r[i] = (*fetch)(b)) < 0) || ((rgb->g[i] = (*fetch)(b)) < 0) || ((rgb->b[i] = (*fetch)(b)) < 0)) rgb = free_rgb(rgb); return rgb; } typedef struct RGBint RGBint; struct RGBint { int maxcol; int width; int height; int *r; int *g; int *b; }; RGBint *readppm(Biobuf *b); RGBint *free_rgb(RGBint *rgb);#include #include #include #include #include #include "ifslib.h" int ppm_fd, red_fd, green_fd, blue_fd; int magic, width, height, maxval; float scalar; enum { /* Channel descriptors */ CRGB = 0, /* three channels, no map */ CYCbCr = 1, /* three channels, no map, level-shifted 601 color space */ CY = 2, /* one channel, luminance */ CRGB1 = 3, /* one channel, map present */ CRGBV = 4, /* one channel, map is RGBV, understood */ CRGB24 = 5, /* one channel in correct data order for loadimage(RGB24) */ CRGBA32 = 6, /* one channel in correct data order for loadimage(RGBA32) */ CYA16 = 7, /* one channel in correct data order for loadimage(Grey8+Alpha8) */ CRGBVA16= 8, /* one channel in correct data order for loadimage(CMAP8+Alpha8) */ /* GIF flags */ TRANSP = 1, INPUT = 2, DISPMASK = 7<<2 }; static int bitc, nbit; /* * fetch a non-comment character. */ static int Bgetch(Biobufhdr *b) { int c; for(;;) { c = Bgetc(b); if(c == '#') { while((c = Bgetc(b)) != Beof && c != '\n') ; } return c; } } /* * fetch a nonnegative decimal integer. */ static int Bgetint(Biobufhdr *b) { int c; int i; while((c = Bgetch(b)) != Beof && !isdigit(c)) ; if(c == Beof) return -1; i = 0; do { i = i*10 + (c-'0'); } while((c = Bgetch(b)) != Beof && isdigit(c)); return i; } static int Bgetdecimalbit(Biobufhdr *b) { int c; while((c = Bgetch(b)) != Beof && c != '0' && c != '1') ; if(c == Beof) return -1; return c == '1'; } static int Bgetbit(Biobufhdr *b) { if(nbit == 0) { nbit = 8; bitc = Bgetc(b); if(bitc == -1) return -1; } nbit--; return (bitc >> (nbit-1)) & 0x1; } static void Bflushbit(Biobufhdr*) { nbit = 0; } typedef struct Pix Pix; struct Pix { char magic; int maxcol; int (*fetch)(Biobufhdr*); int nchan; int chandesc; int invert; void (*flush)(Biobufhdr*); }; static Pix pix[] = { { '1', 1, Bgetdecimalbit, 1, CY, 1, nil }, /* portable bitmap */ { '4', 1, Bgetbit, 1, CY, 1, Bflushbit }, /* raw portable bitmap */ { '2', 0, Bgetint, 1, CY, 0, nil }, /* portable greymap */ { '5', 0, Bgetc, 1, CY, 0, nil }, /* raw portable greymap */ { '3', 0, Bgetint, 3, CRGB, 0, nil }, /* portable pixmap */ { '6', 0, Bgetc, 3, CRGB, 0, nil }, /* raw portable pixmap */ { 0 }, }; int readppm(Biobuf *b) { int i, ch, r, c, fd; int maxcol, nchan, invert; int (*fetch)(Biobufhdr*); uchar *rbuff=nil, *gbuff=nil, *bbuff=nil; char buf[ERRMAX]; char *e; Pix *p; e = "bad file format"; if(Bgetc(b) != 'P') goto Error; c = Bgetc(b); for(p=pix; p->magic; p++) if(p->magic == c) break; if(p->magic == 0) goto Error; if(c != '3' && c != '6') { e = "sorry, RGB only"; goto Error; } width = Bgetint(b); height = Bgetint(b); if(width <= 0 || height <= 0) goto Error; if(! set_width(width) ) { e = "couldn't set width"; goto Error; } if(! set_height(height)) { e = "couldn't set height"; goto Error; } rbuff = (uchar*)emallocz(width); gbuff = (uchar*)emallocz(width); bbuff = (uchar*)emallocz(width); maxcol = p->maxcol; if(maxcol == 0) { maxcol = Bgetint(b); if(maxcol <= 0) goto Error; } e = "error reading file"; fetch = p->fetch; nchan = p->nchan; invert = p->invert; for(r=0; r 2) usage(); ppm_fd = 0; if(argv[1]) ppm_fd = get_fd(argv[1], OREAD); red_fd = get_fd("red", OWRITE); green_fd = get_fd("green", OWRITE); blue_fd = get_fd("blue", OWRITE); Binit(&b, ppm_fd, OREAD); readppm(&b); close(ppm_fd); close(red_fd); close(green_fd); close(blue_fd); if(errstr) fprint(2, "Error : %s\n", errstr); exits(errstr); }#!/bin/rc imagefs -m /mnt/alf cd /mnt/alf/testcard /usr/matt/imagefs/import_tga /usr/matt/imagefs/500x500.tga #include #include #define GBIT16(p) ((p)[0]|((p)[1]<<8)) // 8c import_tga.c && 8l import_tga.8 && mv 8.out import_tga && ./tester.rc int tga_fd; uchar identsize; uchar colourmaptype; uchar imagetype; ushort colourmapstart; ushort colourmaplength; uchar colourmapbits; ushort xstart; ushort ystart; ushort width; ushort height; uchar bits; uchar descriptor; char *comment; void * emalloc(ulong size) { void* m; m = malloc(size); if(m) return m; exits("out of memory"); return nil; // stop compiler warning } char * read_header(void) { uchar header[18]; if(read(tga_fd, &header, 18) != 18) { return smprint("read failed"); } identsize = header[0]; colourmaptype = header[1]; imagetype = header[2]; colourmapstart = GBIT16(&header[3]); colourmaplength = GBIT16(&header[5]); colourmapbits = header[7]; xstart=GBIT16(&header[8]); ystart=GBIT16(&header[10]); width = GBIT16(&header[12]); height = GBIT16(&header[14]); bits=header[16]; descriptor=header[17]; return nil; } char * prepare_bitmap(void) { int fd; fd = open("width", ORDWR); if(fd < 0) return smprint("open width failed"); fprint(fd, "%d", width); close(fd); fd = open("height", ORDWR); if(fd < 0) return smprint("open height failed"); fprint(fd, "%d", height); close(fd); return nil; } char * import_greyscale(void) { int fdg; uchar *buffer; ushort row, readbytes; readbytes = 0; fdg = open("grey", OWRITE|OTRUNC); if(fdg < 0) return 0; buffer = (uchar*) emalloc(width); for(row=0; row < height; row++) { readbytes = readn(tga_fd, buffer, width); if(readbytes != width) break; write(fdg, buffer, width); } close(fdg); free(buffer); if(readbytes == width) return nil; return smprint("bad read, not enough data"); } char * import_rgb(void) { int fdr, fdg, fdb; uchar *buffer, *rbuffer, *gbuffer, *bbuffer; ushort row, rowbytes, readbytes=0, i, k, c; fdr = open("red", OWRITE|OTRUNC); fdg = open("green", OWRITE|OTRUNC); fdb = open("blue", OWRITE|OTRUNC); if(fdr < 0 || fdg < 0 || fdb < 0) return 0; rowbytes = 3 * width; buffer = (uchar*) emalloc(rowbytes); bbuffer = (uchar*) emalloc(width); rbuffer = (uchar*) emalloc(width); gbuffer = (uchar*) emalloc(width); for(row=0; row < height; row++) { readbytes = readn(tga_fd, buffer, rowbytes); if(readbytes != rowbytes) break; i = k = 0; for(c=0; c < width; c++) { bbuffer[i] = buffer[k++]; gbuffer[i] = buffer[k++]; rbuffer[i] = buffer[k++]; i++; } write(fdr, rbuffer, width); write(fdg, gbuffer, width); write(fdb, bbuffer, width); } close(fdb); close(fdr); close(fdg); free(buffer); free(bbuffer); free(rbuffer); free(gbuffer); if(readbytes == rowbytes) return nil; return smprint("bad read, not enough data"); } char * import_rgba(void) { int fdr, fdg, fdb, fda; uchar *buffer, *rbuffer, *gbuffer, *bbuffer, *abuffer; ushort row, rowbytes, readbytes, i, k, c; readbytes = 0; fdr = open("red", OWRITE|OTRUNC); fdg = open("green", OWRITE|OTRUNC); fdb = open("blue", OWRITE|OTRUNC); fda = open("alpha", OWRITE|OTRUNC); if(fdr < 0 || fdg < 0 || fdb < 0 || fda < 0) return 0; rowbytes = 4 * width; buffer = (uchar*) emalloc(rowbytes); bbuffer = (uchar*) emalloc(width); rbuffer = (uchar*) emalloc(width); gbuffer = (uchar*) emalloc(width); abuffer = (uchar*) emalloc(width); for(row=0; row < height; row++) { readbytes = readn(tga_fd, buffer, rowbytes); if(readbytes != rowbytes) break; i = k = 0; for(c=0; c < width; c++) { bbuffer[i] = buffer[k++]; gbuffer[i] = buffer[k++]; rbuffer[i] = buffer[k++]; abuffer[i] = buffer[k++]; i++; } write(fdb, bbuffer, width); write(fdr, rbuffer, width); write(fdg, gbuffer, width); write(fda, abuffer, width); } close(fdb); close(fdr); close(fdg); close(fda); free(buffer); free(bbuffer); free(rbuffer); free(gbuffer); free(abuffer); if(readbytes == width) return nil; return smprint("bad read, not enough data"); } void usage(void) { fprint(2, "usage: import_tga filename\n"); exits("usage"); } void main(int argc, char **argv) { int ctl; char *errstr = nil; if(argc > 2) usage(); tga_fd = 0; if(argv[1]) { tga_fd = open(argv[1], OREAD); if(tga_fd < 0) { fprint(2, "open for read failed : %s\n", argv[1]); exits("open failed"); } } if((errstr = read_header()) == nil) { if(colourmaptype == 0 && (imagetype==2 || imagetype ==3)) { if((errstr = prepare_bitmap()) == nil) { switch(bits) { case 8 : errstr = import_greyscale(); break; case 24 : errstr = import_rgb(); break; case 32 : errstr = import_rgba(); break; } } } else { errstr = smprint("only uncompressed TGAs catered for, sorry"); } } close(tga_fd); if(errstr) fprint(2, "Error : %s\n", errstr); exits(errstr); }#include #include #include #include "ifslib.h" void main(int argc, char **argv) { char *errstr = nil; int pixels, i; int fd; uchar *data; if(argc != 2) bail("usage: invert_channel channel_name"); pixels = get_width() * get_height(); data = read_channel_data(argv[1], pixels); for(i = 0; i < pixels; i++) data[i] = 255 - data[i]; errstr = write_channel_data(argv[1], pixels, data); free(data); bail(errstr); } /usr/maht/imgfs.tgz contrib:V: 9fs srcs cp INDEX *.[ch] *.rc mkfile *.convolution /n/srcs/contrib/maht/imgfs untested and unused, should just be a filter int output_bytes_as(int fd, Bitmap *img, int id, char *fmt) { char *spc_format=nil; int x, y; int i; Channel *c; if(fmt) spc_format = sprint(" %s", fmt); if (spc_format) { if ((c = get_channel(img, id)) == nil) return 0; if(c->data == nil) return 0; if(img->height > 0) && ( img->width > 0) { i = 0; for (y=0; yheight; y++) { fprint(fd, fmt, c->data[i++]); for (x=1; xwidth; x++) fprint(fd, spc_format, c->data[i++]); fprint(fd, "\n"); } return 1; } } return 0; } int output_channel_as_dec(int fd, Bitmap* img, int id) { return output_bytes_as(fd, img, id, "%03d"); } int output_channel_as_hex(int fd, Bitmap* img, int id) { return output_bytes_as(fd, img, id, "%02x"); } uchar* load_channel_from_dec(Biobuf *b, int width, int height) { char *row, **pointers; int num_tokens, k, i; uchar* channel; channel = emallocz(width * height); if(!channel) return nil; pointers = malloc(width * sizeof(char)); for(k=0; k #include #include #include #include #include // #include "ifslib.h" // 8c print_subfont_header.c && 8l print_subfont_header.8 && mv 8.out print_subfont_header // print_subfont_header /usr/matt/ink/l_10646/l_10646.20.00a0 // xd /usr/matt/ink/l_10646/l_10646.20.00a0 > /mnt/acme/new/body static int bitc, nbit; /* * fetch a non-comment character. */ static int Bgetch(Biobufhdr *b) { int c; for(;;) { c = Bgetc(b); if(c == '#') { while((c = Bgetc(b)) != Beof && c != '\n') ; } return c; } } /* * fetch a nonnegative decimal integer. */ static int Bgetint(Biobufhdr *b) { int c; int i; while((c = Bgetch(b)) != Beof && !isdigit(c)) ; if(c == Beof) return -1; i = 0; do { i = i*10 + (c-'0'); } while((c = Bgetch(b)) != Beof && isdigit(c)); return i; } static int Bgetdecimalbit(Biobufhdr *b) { int c; while((c = Bgetch(b)) != Beof && c != '0' && c != '1') ; if(c == Beof) return -1; return c == '1'; } static int Bgetbit(Biobufhdr *b) { if(nbit == 0) { nbit = 8; bitc = Bgetc(b); if(bitc == -1) return -1; } nbit--; return (bitc >> (nbit-1)) & 0x1; } static void Bflushbit(Biobufhdr*) { nbit = 0; } void main (int argc, char **argv) { int font_fd ; Biobuf b; uchar *buff; char *chan; Rectangle r; int fd_src; int nexty, blocklength; int i, n, height, ascent; int x, top, bottom, left, width; fd_src = open(argv[1], OREAD); Binit(&b, fd_src, OREAD); buff = (uchar*)Brdstr(&b, '\n', 1); free(buff); chan = (char*) malloc(12); Bread(&b, chan, 12); free(chan); r.min.x = Bgetint(&b); r.min.y = Bgetint(&b); r.max.x = Bgetint(&b); r.max.y = Bgetint(&b); print("r.min.x %d r.min.y %d r.max.x %d r.max.y %d\n", r.min.x, r.min.y, r.max.x, r.max.y); nexty = Bgetint(&b); blocklength = Bgetint(&b); while(nexty < r.max.y) { Bseek(&b, blocklength, 1); nexty = Bgetint(&b); blocklength = Bgetint(&b); } Bseek(&b, blocklength, 1); n = Bgetint(&b); height = Bgetint(&b); ascent = Bgetint(&b); print("n:%d height:%d ascent:%d \n", n, height, ascent); buff = (uchar*)malloc(6); if(buff == nil) exits("no memory for 6 bytes!"); for(i=0; i<=n; i++) { Bread(&b, buff, 6); x = GBIT16(&buff[0]); top = buff[2]; bottom = buff[3]; left = buff[4]; width = buff[5]; print("x:%d top:%d bottom:%d left:%d width:%d\n", x, top, bottom, left, width); } free(buff); close(fd_src); exits(0); }#include #include // 8c read9p.c && 8l read9p.8 && ./8.out void main(int argc, char **argv) { 2 > 1 ? print("yes") : print("no"); } #include #include #include // 8c -w readtga.c && 8l -o readtga readtga.8 && ./readtga // 8c readtga.c && 8l -o readtga readtga.8 && ./readtga #define GBIT16(p) ((p)[0]|((p)[1]<<8)) #define PBIT8(p,v) (p)[0]=(v) #define PBIT16(p,v) (p)[0]=(v);(p)[1]=(v)>>8 typedef struct RGBA { int width; int height; uchar* r; uchar* g; uchar* b; uchar* a; } RGBA ; void RGBA_free(RGBA *rgba) { free(rgba->r); free(rgba->g); free(rgba->b); free(rgba->a); free(rgba); } uchar * allocate_channel(int pixels) { uchar *ch; ch = (uchar*) mallocz(pixels, 1); return ch; } int allocate_rgb(RGBA* rgb) { int pixels; pixels = rgb->width * rgb->height; rgb->r = allocate_channel(pixels); rgb->g = allocate_channel(pixels); rgb->b = allocate_channel(pixels); if (rgb->r && rgb->g && rgb->b) return 1; free(rgb->r); free(rgb->g); free(rgb->b); return 0; } int allocate_rgba(RGBA* rgba) { if (allocate_rgb(rgba)) { rgba->a = allocate_channel(rgba->width * rgba->height); return (rgba->a != nil); } free(rgba->r); free(rgba->g); free(rgba->b); free(rgba->a); return 0; } int read_tga_g(int fd, RGBA* rgb) { uchar *buffer; int row, rowbytes, n, i, k,c; rowbytes = rgb->width; buffer = (uchar*) malloc(rowbytes); if (buffer == nil) return 0; i = 0; for(row=0; row < rgb->height; row++) { n = readn(fd, buffer, rowbytes); if(n != rowbytes) return 0; k = 0; for(c=0; c < rgb->width; c++) { rgb->g[i] = buffer[k++]; i++; } } return 1; } int read_tga_bgr(int fd, RGBA* rgb) { uchar *buffer; int row, rowbytes, n, i, k,c; rowbytes = 3 * rgb->width; buffer = (uchar*) malloc(rowbytes); if (buffer == nil) return 0; i = 0; for(row=0; row < rgb->height; row++) { n = readn(fd, buffer, rowbytes); if(n != rowbytes) return 0; k = 0; for(c=0; c < rgb->width; c++) { rgb->b[i] = buffer[k++]; rgb->r[i] = buffer[k++]; rgb->g[i] = buffer[k++]; i++; } } return 1; } int read_tga_bgra(int fd, RGBA* rgba) { uchar *buffer; int row, rowbytes, n, i, k,c; rowbytes = 4 * rgba->width; buffer = (uchar*) malloc(rowbytes); if (buffer == nil) return 0; i = 0; for(row=0; row < rgba->height; row++) { n = readn(fd, buffer, rowbytes); if(n != rowbytes) return 0; k = 0; for(c=0; c < rgba->width; c++) { rgba->b[i] = buffer[k++]; rgba->r[i] = buffer[k++]; rgba->g[i] = buffer[k++]; rgba->a[i] = buffer[k++]; i++; } } return 1; } void output_channel_as_dec(int fd, RGBA* img, uchar* pixels) { int x, y; int i; i = 0; for (y=0; yheight; y++) { fprint(fd, "%03d", pixels[i++]); for (x=1; xwidth; x++) fprint(fd, " %03d", pixels[i++]); fprint(fd, "\n"); } } void output_channel_as_hex(int fd, RGBA* img, uchar* pixels) { int x, y; int i; i = 0; for (y=0; yheight; y++) { fprint(fd, "%02xd", pixels[i++]); for (x=1; xwidth; x++) fprint(fd, " %02x", pixels[i++]); fprint(fd, "\n"); } } uchar* load_channel_from_dec(Biobuf *b, int width, int height) { char *row, **pointers; int num_tokens, k, i; uchar* channel; channel = mallocz(width * height, 1); if(!channel) return nil; pointers = malloc(width * sizeof(char)); for(k=0; kr && rgba->g && rgba->b)) return 0; memset(header, 0, 18); header[2] = 2; header[7] = 24; PBIT16(&header[12], rgba->width); PBIT16(&header[14], rgba->height); header[16] = 24; pixels = rgba->width * rgba->height; write(fd, header, 18); k=0; for(i=0; ib[k], 1); write(fd, &rgba->g[k], 1); write(fd, &rgba->r[k++], 1); } return 1; } int write_rgba_tga(int fd, RGBA* rgba) { int pixels, i, k; char header[18]; if(!(rgba->r && rgba->g && rgba->b && rgba->a)) return 0; memset(header, 0, 18); header[2] = 2; header[7] = 32; PBIT16(&header[12], rgba->width); PBIT16(&header[14], rgba->height); header[16] = 24; pixels = rgba->width * rgba->height; write(fd, header, 18); k=0; for(i=0; ib[k], 1); write(fd, &rgba->r[k], 1); write(fd, &rgba->g[k], 1); write(fd, &rgba->a[k++], 1); } return 1; } int write_g_tga(int fd, RGBA* rgba) { int pixels, i; char header[18]; if(!rgba->g) return 0; memset(header, 0, 18); header[2] = 2; header[7] = 8; PBIT16(&header[12], rgba->width); PBIT16(&header[14], rgba->height); header[16] = 8; pixels = rgba->width * rgba->height; write(fd, header, 18); for(i=0; ig[i], 1); return 1; } int write_a_tga(int fd, RGBA* rgba) { int pixels, i; char header[18]; if(!rgba->a) return 0; memset(header, 0, 18); header[2] = 2; header[7] = 8; PBIT16(&header[12], rgba->width); PBIT16(&header[14], rgba->height); header[16] = 8; pixels = rgba->width * rgba->height; write(fd, header, 18); for(i=0; ia[i], 1); return 1; } RGBA* read_tga(int fd) { char header[18]; RGBA *rgba; int bits, desc, xstart, ystart, success; read(fd, &header, 18); rgba = (RGBA*)mallocz(sizeof(RGBA), 1); rgba->width = GBIT16(&header[12]); rgba->height = GBIT16(&header[14]); xstart=GBIT16(&header[8]); ystart=GBIT16(&header[10]); bits=header[16]; desc=header[17]; success = 0; switch(bits) { case 8 : rgba->g = allocate_channel(rgba->width * rgba->height); if (rgba->g != nil) success = read_tga_g(fd, rgba); break; case 24 : if ( allocate_rgb(rgba)) success = read_tga_bgr(fd, rgba); break; case 32 : if ( allocate_rgba(rgba)) success = read_tga_bgra(fd, rgba); break; } if (success) return rgba; return nil; } RGBA * get_rgba(void) { RGBA *rgba = nil; int fd; fd = open("/usr/matt/tc.tga", OREAD); if (fd > -1) { rgba = read_tga(fd); close(fd); } else { exits("open failed"); } return rgba; } void main(int argc, char **argv) { RGBA *rgba; Biobuf *bp; int tgafd; rgba = get_rgba(); if (rgba) { bp = Bopen("/usr/matt/imagefs/txt.txt", OREAD); rgba->r = load_channel_from_dec(bp, 3, 3); free(bp); tgafd = open("/usr/matt/imagefs/out.tga", OWRITE|OTRUNC); if(tgafd < 0) print("hmm tgafd failed"); write_rgb_tga(tgafd, rgba); close(tgafd); // RGBA_free(rgba); } else { exits("allocated failed"); } exits(0); } #!/bin/rc for (c in red green blue) blit_channel $* $c plumb -d image ppm #include "sample_convolved.h" typedef struct Columns Columns; typedef struct Row Row; struct Columns { char *entries[256]; int count; }; struct Row { Columns; Row *next; }; int next_pair(float *ix, float *iy) { if(Bread(&bin, ix, sizeof(float)) < sizeof(float) || Bread(&bin, iy, sizeof(float)) < sizeof(float)) return 0; return 1; } void free_rows(Row *first) { Row *t, *row; for(row = first->next; row; row = t) { t = row->next; free(row); } } void fill_convolution(Row *first) { Row *t, *row; int e, k, i = 0; int *coeff; int divisor = 1; coeff = (int*)malloc(sizeof(int) * convolution.rows * convolution.columns); for(row = first; row; row = t) { t = row->next; e = 0; for(k = 0; k < row->count; k++, i++) { coeff[i] = atof(row->entries[e++]); divisor += coeff[i]; } } e = convolution.rows * convolution.columns; convolution.coefficient = (float*)malloc(sizeof(float) * e); if(fabs(divisor) > 0) for(i=0; i < e; i++) convolution.coefficient[i] = (float)coeff[i] / divisor; else for(i=0; i < e; i++) convolution.coefficient[i] = (float)coeff[i]; free(coeff); } void print_convolution(void) { print("size %d, %d\n", convolution.columns, convolution.rows); int i, k, j = 0; if(! convolution.coefficient) bail("ack, no coefficients"); for(i = 0; i < convolution.rows; i++) { for(k = 0; k < convolution.columns; k++) { print("[%0.2f] ", convolution.coefficient[j++]); } print("\n"); } } int read_convolution(int fd) { Biobuf b; Binit(&b, fd, OREAD); Row firstrow, *row; char *line; convolution.rows = 0; convolution.columns = 0; convolution.coefficient= nil; line = Brdstr(&b, '\n', 1); if(line) { convolution.columns = firstrow.count = getfields(line, firstrow.entries, 256, 1, " \t"); convolution.rows++; } row = &firstrow; while(line && row->count) { row->next = (Row*)mallocz(sizeof(Row), 1); if(row->next) { row = row->next; line = Brdstr(&b, '\n', 1); if(line) { row->count = getfields(line, row->entries, 256, 1, " \t"); if(row->count != convolution.columns) { free_rows(&firstrow); bail("Invalid convolution file"); } convolution.rows++; } } else bail("Out of memory"); } fill_convolution(&firstrow); free_rows(&firstrow); return convolution.coefficient == nil; } uchar sample(float ix, float iy) { int i, j, k; float pixel, sx, l, c; uchar p; sx = ix + shift.x; iy += shift.y; j = 0; for(i = 0; i < convolution.rows; i++, iy += 1) { for(ix = sx, k = 0; k < convolution.columns; k++, ix += 1) { p = get_pixel(data, WIDTH, HEIGHT, ix, iy, wrap); c = convolution.coefficient[j++]; l = (float)p * c; pixel += l; } } if(pixel > 255.0) return 255; if(pixel < 0) return 0; return (uchar) pixel; } void main(int argc, char **argv) { char *fname; int fd; float ix, iy; shift = (Cart) {0,0}; ARGBEGIN{ case 'w' : WIDTH = atoi(ARGF()); break; case 'h' : HEIGHT = atoi(ARGF()); break; case 'x' : shift.x = atof(ARGF()); break; case 'y' : shift.y = atof(ARGF()); break; case 'f' : fname = ARGF(); if(strcmp("-", fname) != 0) fdin = open(fname, OREAD); break; case 'o' : fname = ARGF(); if(strcmp("-", fname) != 0) fdout = open(fname, OWRITE); break; case 'm' : wrap = 2; break; case 'c' : fd = open(ARGF(), OREAD); if(fd < 0) bail("usage : sample_convolved -w width -h height -c convolution_file [-f float_list -o fileout -m (mirror)] src_channel"); read_convolution(fd); break; }ARGEND; if(argc != 1 || fdin < 0 || fdout < 0 || WIDTH < 1 || HEIGHT < 1) bail("sneaked usage : usage : sample_convolved -w width -h height -c convolution_file [-f float_list -o fileout -m (mirror)] src_channel"); Binit(&bin, fdin, OREAD); Binit(&bout, fdout, OWRITE); data = read_channel_data(argv[0], WIDTH * HEIGHT); while(next_pair(&ix, &iy)) { Bputc(&bout, sample(ix, iy)); } Bterm(&bin); Bterm(&bout); } /* Put mk install ; imgfs/import_ppm /usr/maht/imgfs/arabian.ppm ; ramfs ; touch /tmp/pixels ; imgfs/sample_convolved -w `{cat width} -h `{cat height} -c /usr/maht/imgfs/c9.convolution -f /usr/maht/imgfs/spiral_500x274.floats -o /tmp/pixels red ; cat /tmp/pixels > red ; imgfs/sample_convolved -w `{cat width} -h `{cat height} -c /usr/maht/imgfs/c9.convolution -f /usr/maht/imgfs/spiral_500x274.floats -o /tmp/pixels green ; cat /tmp/pixels > green ; imgfs/sample_convolved -w `{cat width} -h `{cat height} -c /usr/maht/imgfs/c9.convolution -f /usr/maht/imgfs/spiral_500x274.floats -o /tmp/pixels blue ; cat /tmp/pixels > blue */ #include #include #include #include #include "ifslib.h" typedef struct Convolution Convolution; struct Convolution { int rows; int columns; float *coefficient; }; typedef struct Cart Cart; struct Cart { float x; float y; }; int WIDTH = 0; int HEIGHT = 0; int wrap = 1; uchar *data = nil; int fdin = 0; // stdin int fdout = 1; // Cart shift; Biobuf bin; Biobuf bout; int next_pair(float *ix, float *iy); Convolution convolution; #include "sample_linear.h" int next_pair(float *ix, float *iy) { if(Bread(&bin, ix, sizeof(float)) < sizeof(float) || Bread(&bin, iy, sizeof(float)) < sizeof(float)) return 0; return 1; } void main(int argc, char **argv) { char *fname; uchar *data; int wrap = 1; float ix, iy; ARGBEGIN{ case 'w' : WIDTH = atoi(ARGF()); break; case 'h' : HEIGHT = atoi(ARGF()); break; case 'f' : fname = ARGF(); if(strcmp("-", fname) != 0) fdin = open(fname, OREAD); break; case 'o' : fname = ARGF(); if(strcmp("-", fname) != 0) fdout = open(fname, OWRITE); break; case 'm' : wrap = 2; break; }ARGEND; if(argc != 1 || fdin < 0 || fdout < 0 || WIDTH < 1 || HEIGHT < 1) bail("usage : sample_linear -w width -h height [-f float_list -o fileout -m (mirror)] src_channel"); Binit(&bin, fdin, OREAD); Binit(&bout, fdout, OWRITE); data = read_channel_data(argv[0], WIDTH * HEIGHT); while(next_pair(&ix, &iy)) Bputc(&bout, get_pixel(data, WIDTH, HEIGHT, ix, iy, wrap)); Bterm(&bin); Bterm(&bout); } /* Put mk install imagefs/import_ppm /usr/maht/imgfs/arabian.ppm ; imagefs/sample_linear -w `{cat width} -h `{cat height} -f /usr/maht/imgfs/spiral_500x274.floats -o /tmp/pixels red */ #include #include #include #include #include "ifslib.h" int WIDTH = 0; int HEIGHT = 0; int fdin = 0; // stdin int fdout = 1; // Biobuf bin; Biobuf bout; int next_pair(float *ix, float *iy); #include "sample_linear.h" int next_pair_Rdline(float *ix, float *iy) { char *f = Brdline(&bin, ' '); if(f) { *ix = atof(f); f = Brdline(&bin, '\n'); if(f) { *iy = atof(f); return 1; } } return 0; } int next_pair_Rdstr(float *ix, float *iy) { char *x = Brdstr(&bin, '\n', 1); char *y; if(x) { *ix = strtod(x, &y); *iy = atof(y); return 1; } return 0; } void main(int argc, char **argv) { char *fname; uchar *data; int wrap = 1; float ix, iy; ARGBEGIN{ case 'w' : WIDTH = atoi(ARGF()); break; case 'h' : HEIGHT = atoi(ARGF()); break; case 'f' : fname = ARGF(); if(strcmp("-", fname) != 0) fdin = open(fname, OREAD); break; case 'o' : fname = ARGF(); if(strcmp("-", fname) != 0) fdout = open(fname, OWRITE); break; case 'm' : wrap = 2; break; }ARGEND; if(argc != 1 || fdin < 0 || fdout < 0 || WIDTH < 1 || HEIGHT < 1) bail("usage : sample_linear -w width -h height [-f float_list -o fileout -m (mirror)] src_channel"); Binit(&bin, fdin, OREAD); Binit(&bout, fdout, OWRITE); data = read_channel_data(argv[0], WIDTH * HEIGHT); while(next_pair_Rdstr(&ix, &iy)) Bputc(&bout, get_pixel(data, WIDTH, HEIGHT, ix, iy, wrap)); Bterm(&bin); Bterm(&bout); } /* Put mk install imagefs/import_ppm /usr/maht/imgfs/arabian.ppm ; imagefs/sample_linear -w `{cat width} -h `{cat height} */ #include #include #include #include #include "ifslib.h" int WIDTH = 0; int HEIGHT = 0; int fdin = 0; // stdin int fdout = 1; // Biobuf bin; Biobuf bout; #!/bin/rc cmd = $1 shift args = `{echo -n $1} shift for(a in $*) { $cmd $args $a & } wait # spawn echo '-n 5 ' (1 2 3) #include "spiral.h" double logbase(double value, double base) { return log(value) / log(base); } double fractional(double value) { return value - floor(value); } double positiveatan2(double y, double x) { double result = atan2(y, x); return result < 0.0 ? result + pi2 : result; } double delog(double value, double base) { //takes a value from 0-1 return (pow(base, value)-1)/(base - 1); } void sample_point(float x, float y,float *ix, float *iy) { int i = 0; float dx = x - spiral_centre_x; float dy = y - spiral_centre_y; float r = sqrt(dx * dx + dy * dy); float theta = positiveatan2(y - spiral_centre_y, x - spiral_centre_x); float times_around; if(r > 0) times_around = logbase(r, tightness) - (theta / pi2); else times_around = 1; float source_r = ring_inner_radius + (ring_outer_radius - ring_inner_radius) * delog(fractional(times_around), tightness); float source_theta = twist_factor * (rotation_offset + theta + pi2 * floor(times_around)); *ix = ring_x + source_r * cos(source_theta); *iy = ring_y + source_r * sin(source_theta); } void main(int argc, char **argv) { char *errstr = nil; int pixels, i, x, y; uchar *data_in, *data_out; float ix, iy; int centre_spiral_y = 1; int centre_spiral_x = 1; int centre_ring_y = 1; int centre_ring_x = 1; int set_inner_radius = 1; int set_outer_radius = 1; ARGBEGIN{ case 'X': spiral_centre_x = atof(ARGF()); centre_spiral_x = 0; break; case 'Y': spiral_centre_y = atof(ARGF()); centre_spiral_y = 0; break; case 'x' : ring_x = atof(ARGF()); centre_ring_x = 0; break; case 'y' : ring_y = atof(ARGF()); centre_ring_y = 0; break; case 'i': ring_inner_radius = atof(ARGF()); set_inner_radius = 0; break; case 'o' : ring_outer_radius = atof(ARGF()); set_outer_radius = 0; break; case 't' : twist_factor = atof(ARGF()); break; case 'r' : rotation_offset = atof(ARGF()); break; }ARGEND; if(argc != 1) bail("usage : spiral [-X spiral_centre_x -Y spiral_centre_y -x ring_x -y ring_y -i inner_radius -o outer_radius -t twist_factor -r rotation_offset] channel"); pi2 = 2 * PI; WIDTH = get_width(); HEIGHT = get_height(); pixels = WIDTH * HEIGHT; data_in = read_channel_data(argv[0], pixels); data_out = (uchar*) emalloc(pixels); if(centre_spiral_x) spiral_centre_x = WIDTH / 2; if(centre_spiral_y) spiral_centre_y = HEIGHT / 2; if(centre_ring_x) ring_x = WIDTH / 2; if(centre_ring_y) ring_y = HEIGHT / 2; if(set_outer_radius) { if(WIDTH > HEIGHT) ring_outer_radius = HEIGHT / 2; else ring_outer_radius = WIDTH / 2; } if(set_inner_radius) { if(WIDTH > HEIGHT) ring_inner_radius = HEIGHT / 4; else ring_inner_radius = WIDTH / 4; } tightness = ring_outer_radius / ring_inner_radius; i = 0; for(y = 0; y < HEIGHT; y++) { for(x = 0; x < WIDTH; x++) { sample_point(x, y, &ix, &iy); data_out[i++] = get_pixel(data_in, WIDTH, HEIGHT, ix, iy, 1); } } errstr = write_channel_data(argv[0], pixels, data_out); free(data_out); free(data_in); } /* imagefs/import_ppm /n/momo/tmp/arabian.ppm for (c in (red green blue)) imagefs/spiral $c */ #include #include #include #include "ifslib.h" int WIDTH, HEIGHT; float spiral_centre_x = 0; float spiral_centre_y = 0; float ring_x = 0; float ring_y = 0; float ring_inner_radius = 5; float ring_outer_radius = 10; float twist_factor = 1; float rotation_offset = 0; float pi2; float tightness; #include "spiral_gen.h" void bail(char *msg) { if(msg) fprint(2, msg); exits(msg); } double logbase(double value, double base) { return log(value) / log(base); } double fractional(double value) { return value - floor(value); } double positiveatan2(double y, double x) { double result = atan2(y, x); return result < 0.0 ? result + pi2 : result; } double delog(double value, double base) { //takes a value from 0-1 return (pow(base, value)-1)/(base - 1); } void sample_point(int x, int y) { float dx = x - spiral_centre_x; float dy = y - spiral_centre_y; float r = sqrt(dx * dx + dy * dy); float theta = positiveatan2(y - spiral_centre_y, x - spiral_centre_x); float times_around; float f; if(r > 0) times_around = logbase(r, tightness) - (theta / pi2); else times_around = 1; float source_r = ring_inner_radius + (ring_outer_radius - ring_inner_radius) * delog(fractional(times_around), tightness); float source_theta = twist_factor * (rotation_offset + theta + pi2 * floor(times_around)); f = ring_x + source_r * cos(source_theta); Bwrite(&bufstdout, &f, sizeof(float)); f = ring_y + source_r * sin(source_theta); Bwrite(&bufstdout, &f, sizeof(float)); } void main(int argc, char **argv) { int x, y; int centre_spiral_y = 1; int centre_spiral_x = 1; int centre_ring_y = 1; int centre_ring_x = 1; int set_inner_radius = 1; int set_outer_radius = 1; ARGBEGIN{ case 'w' : WIDTH = atoi(ARGF()); break; case 'h' : HEIGHT = atoi(ARGF()); break; case 'X': spiral_centre_x = atof(ARGF()); centre_spiral_x = 0; break; case 'Y': spiral_centre_y = atof(ARGF()); centre_spiral_y = 0; break; case 'x' : ring_x = atof(ARGF()); centre_ring_x = 0; break; case 'y' : ring_y = atof(ARGF()); centre_ring_y = 0; break; case 'i': ring_inner_radius = atof(ARGF()); set_inner_radius = 0; break; case 'o' : ring_outer_radius = atof(ARGF()); set_outer_radius = 0; break; case 't' : twist_factor = atof(ARGF()); break; case 'r' : rotation_offset = atof(ARGF()); break; }ARGEND; if(argc != 0 || WIDTH < 1 || HEIGHT < 1) bail("usage : spiral_gen -w width -h height [-X spiral_centre_x -Y spiral_centre_y -x ring_x -y ring_y -i inner_radius -o outer_radius -t twist_factor -r rotation_offset]"); pi2 = 2 * PI; Binit(&bufstdout, 1, OWRITE); if(centre_spiral_x) spiral_centre_x = WIDTH / 2; if(centre_spiral_y) spiral_centre_y = HEIGHT / 2; if(centre_ring_x) ring_x = WIDTH / 2; if(centre_ring_y) ring_y = HEIGHT / 2; if(set_outer_radius) { if(WIDTH > HEIGHT) ring_outer_radius = HEIGHT / 2; else ring_outer_radius = WIDTH / 2; } if(set_inner_radius) { if(WIDTH > HEIGHT) ring_inner_radius = HEIGHT / 4; else ring_inner_radius = WIDTH / 4; } tightness = ring_outer_radius / ring_inner_radius; for(y = 0; y < HEIGHT; y++) for(x = 0; x < WIDTH; x++) sample_point(x, y); Bterm(&bufstdout); } /* Put 8c spiral_gen.c && 8l spiral_gen.8 && mv 8.out spiral_gen && spiral_gen -w 1024 -h 1024 -i 10 -o 612 -t 4 > spiral_1024x1024.twisty.floats */ #include #include #include int WIDTH = 0; int HEIGHT = 0; float spiral_centre_x = 0; float spiral_centre_y = 0; float ring_x = 0; float ring_y = 0; float ring_inner_radius = 5; float ring_outer_radius = 10; float twist_factor = 1; float rotation_offset = 0; float pi2; float tightness; Biobuf bufstdout; #include "spiral_gen.h" void bail(char *msg) { if(msg) fprint(2, msg); exits(msg); } double logbase(double value, double base) { return log(value) / log(base); } double fractional(double value) { return value - floor(value); } double positiveatan2(double y, double x) { double result = atan2(y, x); return result < 0.0 ? result + pi2 : result; } double delog(double value, double base) { //takes a value from 0-1 return (pow(base, value)-1)/(base - 1); } void sample_point(int x, int y) { float dx = x - spiral_centre_x; float dy = y - spiral_centre_y; float r = sqrt(dx * dx + dy * dy); float theta = positiveatan2(y - spiral_centre_y, x - spiral_centre_x); float times_around; if(r > 0) times_around = logbase(r, tightness) - (theta / pi2); else times_around = 1; float source_r = ring_inner_radius + (ring_outer_radius - ring_inner_radius) * delog(fractional(times_around), tightness); float source_theta = twist_factor * (rotation_offset + theta + pi2 * floor(times_around)); char *floats = smprint("%0.4f %0.4f\n", ring_x + source_r * cos(source_theta), ring_y + source_r * sin(source_theta)); Bwrite(&bufstdout, floats, strlen(floats)); free(floats); } void main(int argc, char **argv) { int x, y; int centre_spiral_y = 1; int centre_spiral_x = 1; int centre_ring_y = 1; int centre_ring_x = 1; int set_inner_radius = 1; int set_outer_radius = 1; ARGBEGIN{ case 'w' : WIDTH = atoi(ARGF()); break; case 'h' : HEIGHT = atoi(ARGF()); break; case 'X': spiral_centre_x = atof(ARGF()); centre_spiral_x = 0; break; case 'Y': spiral_centre_y = atof(ARGF()); centre_spiral_y = 0; break; case 'x' : ring_x = atof(ARGF()); centre_ring_x = 0; break; case 'y' : ring_y = atof(ARGF()); centre_ring_y = 0; break; case 'i': ring_inner_radius = atof(ARGF()); set_inner_radius = 0; break; case 'o' : ring_outer_radius = atof(ARGF()); set_outer_radius = 0; break; case 't' : twist_factor = atof(ARGF()); break; case 'r' : rotation_offset = atof(ARGF()); break; }ARGEND; if(argc != 0 || WIDTH < 1 || HEIGHT < 1) bail("usage : spiral_gen -w width -h height [-X spiral_centre_x -Y spiral_centre_y -x ring_x -y ring_y -i inner_radius -o outer_radius -t twist_factor -r rotation_offset]"); pi2 = 2 * PI; Binit(&bufstdout, 1, OWRITE); if(centre_spiral_x) spiral_centre_x = WIDTH / 2; if(centre_spiral_y) spiral_centre_y = HEIGHT / 2; if(centre_ring_x) ring_x = WIDTH / 2; if(centre_ring_y) ring_y = HEIGHT / 2; if(set_outer_radius) { if(WIDTH > HEIGHT) ring_outer_radius = HEIGHT / 2; else ring_outer_radius = WIDTH / 2; } if(set_inner_radius) { if(WIDTH > HEIGHT) ring_inner_radius = HEIGHT / 4; else ring_inner_radius = WIDTH / 4; } tightness = ring_outer_radius / ring_inner_radius; for(y = 0; y < HEIGHT; y++) for(x = 0; x < WIDTH; x++) sample_point(x, y); Bterm(&bufstdout); } /* Put 8c spiral_gen.c && 8l spiral_gen.8 && 8.out -w 1024 -h 1024 > spiral_1024x1024.floats.ascii */ #include #include void main(void) { print("%d\n", sizeof(float)); } // 8c t.c && 8l t.8 && 8.out#!/bin/rc cd /usr/matt/imagefs_src rm -rf /usr/matt/bin/386/imagefs mk nuke; mk install all bind -b /bin/imagefs /bin imagefs -m /mnt/alf a = text b = crew echo $a > /mnt/alf/new cd /mnt/alf/images/$a import_m8 /tmp/latin.9 cat ppm > /tmp/ohdear exec plumb -d image /tmp/ohdear cd /mnt/alf/images/$b jpg -9 /usr/matt/star-trek.jpg | toppm | import_ppm invert_channel /mnt/alf/images/$b/select for (c in red green blue) { blit_channel -f /mnt/alf/images/$b/$c -t /mnt/alf/images/$b/$c -s 0,0-100,150 -d 0,0-`{cat width} ^',' ^`{cat height} } cat ppm > /tmp/ohdear plumb -d image /tmp/ohdear #include #include #include #include #include "ifslib.h" void main(int argc, char **argv) { char *errstr = nil; int pixels, i, width, height, wrap=0, x, y; int fd; uchar *data_in, *data_out; float xscale=1, yscale=1, xs, w2, h2, dx, dy, dx2, dy2, r, a, aoffset=0.0; ARGBEGIN{ case 'a': aoffset = atof(ARGF()); break; case 'w' : wrap = 1; break; case 'm' : wrap = 2; break; case 'x' : xscale = atof(ARGF()); break; case 'y' : yscale = atof(ARGF()); break; }ARGEND; if(argc != 1) bail("usage : to_polar [-x xscale -a offset_angle -w] channel"); aoffset = radians(aoffset + 90); width = get_width(); height = get_height(); pixels = width * height; data_in = read_channel_data(argv[0], pixels); data_out = (uchar*) emalloc(pixels); w2 = (float)width / 2.0; h2 = (float)height / 2.0; xs = xscale * width / radians(360); dy = - h2; i = 0; for(y = 0; y < height; y++) { dx = -w2; dy2 = dy * dy; for(x=0; x 0) a = asin(dy / r); else a = 0; if (x > w2) a = radians(180) - a; a += aoffset; data_out[i++] = get_pixel(data_in, width, height, a * xs, r * 2 * yscale, wrap); dx += 1; } dy += 1; } errstr = write_channel_data(argv[0], pixels, data_out); free(data_out); free(data_in); bail(errstr); }"ddk '"ddk ',··k 7 bioutils.c,11k 7 bioutils.h0ÙÙk 7blit_channel.c077k 8c25.convolution0k 8c9.convolution*ýýk 7 complex.c*EEk 7 complex.h4k 7 convolute_channel.c4ËËk 7 cp_subfont_header.c*k 7 droste.c*ÙÙk 7droste.h( ææk 7ekko.c.!!# #k 7 export_tga.c,##––k 8  font2m8.rc*$$ùùk 7ifslib.c*((22k 7ifslib.h()),99,k 7imgfp.c(11k 7imgfp.h(22C22Ck 7imgfs.c,99qqk 7 import_m8.c.::EEk 7  import_ppm.c.<<®®k 7" import_ppm.h8==::k 7$import_ppm_standalone.c2@@qqk 8 import_tester.rc.AAk 7& import_tga.c2DDÈÈk 7'invert_channel.c(EE//k 8mkfile2FFXXk 7)output_bytes_as.c,GG··k 8 pagetest.rc8HH­ ­k 7+print_subfont_header.c*JJ——k 7,read9p.c*KKÿÿk 7. readtga.c*OONNk 8 resize.rc4PPöök 70sample_convolved.c4SSÚÚk 72sample_convolved.h0TTÕÕk 73sample_linear.c0UUââk 75sample_linear.h6VV[[k 76sample_linear_ascii.c6WW½½k 78sample_linear_ascii.h*XX{{k 8spawn.rc*YYJ Jk 7:spiral.c*[[@@k 8spiral.h.\\ k 8 spiral_gen.c.^^JJk 8 spiral_gen.h4__à àk 8spiral_gen_ascii.c4^^JJk 8spiral_gen_ascii.h$aattk 8t.c*bb]]k 8 tester.rc,ccqqk 8  to_polar.cdd