#include #include enum { ERR, EOL, MAKE, TERM, }; enum { White, Black, }; typedef struct Tab { ushort run; ushort bits; int code; } Tab; Tab wtab[8192]; Tab btab[8192]; uchar bitrev[256]; uchar bitnonrev[256]; int readrow(uchar *rev, int*); void initwbtab(void); void sync(uchar*); int readfile(int, char*, char*); int nbytes; uchar *bytes; uchar *pixels; uchar *buf; int y; uint bitoffset; uint word24; enum { Bytes = 1024*1024, Lines = 1410, /* 1100 for A4, 1410 for B4 */ Dots = 1728, }; void error(char *fmt, ...) { char buf[256]; va_list arg; if(fmt){ va_start(arg, fmt); vseprint(buf, buf+sizeof buf, fmt, arg); va_end(arg); fprint(2, "g3: %s\n", buf); } exits(fmt); } void usage(void) { fprint(2, "usage: g3p9bit [-gy] file\n"); exits("usage"); } void main(int argc, char **argv) { int y, fd, n, m; char *t; char *file, err[ERRMAX], tbuf[5*12+1]; int gray=0; int yscale=1; ARGBEGIN{ case 'g': /* do simulated 2bit gray to compress x */ gray++; break; case 'y': /* double each scan line to double the y resolution */ yscale=2; break; default: usage(); }ARGEND if(argc > 1) usage(); initwbtab(); buf = malloc(1024*1024); t = malloc((Dots/8)*Lines); if(buf==nil || t==nil) error("malloc failed: %r\n"); pixels = (uchar*)t; file = ""; fd = 0; if(argc > 0){ file = argv[0]; fd = open(file, OREAD); if(fd < 0) error("can't open %s", file); } y = readfile(fd, file, err); if(y < 0) error(err); sprint(tbuf, "%11d %11d %11d %11d %11d ", gray, 0, 0, Dots/(gray+1), y*yscale); write(1, tbuf, 5*12); n = (Dots/8)*y*yscale; /* write in pieces; brazil pipes work badly with huge counts */ while(n > 0){ if(yscale > 1) /* write one scan line */ m = Dots/8; else{ /* write lots */ m = n; if(m > 8192) m = 8192; } for(y=0; y 2){ if(bytes[0]=='\n'){ if(strncmp((char*)bytes+1, "FDCS=", 5) == 0){ i = crackhdr(bytes+6, hdr); if(i < 0){ sprint(err, "g3: bad FDCS in header: %s", file); return -1; } if(hdr[Hwidth] != 0){ sprint(err, "g3: unsupported width: %s", file); return -1; } if(hdr[Hcomp] != 0){ sprint(err, "g3: unsupported compression: %s", file); return -1; } bytes += i+1; nbytes -= i+1; continue; } if(bytes[1] == '\n'){ bytes += 2; nbytes -= 2; break; } } bytes++; nbytes--; } if(nbytes < 2) goto bad; rev = bitnonrev; } bitoffset = 24; word24 = 0; sync(rev); lines = Lines; if(hdr[Hvres] == 1) lines *= 2; for(y=0; y Dots) return 0; if(state == White) tab = wtab; else tab = btab; if(bo > (24-13)) { do { if(nbytes <= 0) return -1; w24 = (w24<<8) | rev[*bytes]; bo -= 8; bytes++; nbytes--; } while(bo >= 8); } t = tab + ((w24 >> (24-13-bo)) & 8191); x += t->run; bo += t->bits; if(t->code == TERM){ if(state == White) oldx = x; else{ oldx2 = oldx; x2 = x; xx = oldx2&7; q = p+oldx2/8; if(x2/8 == oldx2/8) /* all in one byte, but if((x2&7)==0), do harder case */ *q |= (0xFF>>xx) & (0xFF<<(8-(x2&7))); else{ dx = x2 - oldx2; /* leading edge */ if(xx){ *q++ |= 0xFF>>xx; dx -= 8-xx; } /* middle */ while(dx >= 8){ *q++ = 0xFF; dx -= 8; } /* trailing edge */ if(dx) *q |= 0xFF<<(8-dx); } } state ^= White^Black; goto loop; } if(t->code == ERR){ bitoffset = bo; word24 = w24; return 0; } if(t->code == EOL){ bitoffset = bo; word24 = w24; return 1; } goto loop; } void sync(uchar *rev) { Tab *t; int c; c = 0; loop: if(bitoffset > (24-13)) { do { if(nbytes <= 0) return; word24 = (word24<<8) | rev[*bytes]; bitoffset -= 8; bytes++; nbytes--; } while(bitoffset >= 8); } t = wtab + ((word24 >> (24-13-bitoffset)) & 8191); if(t->code != EOL) { bitoffset++; c++; goto loop; } bitoffset += t->bits; } typedef struct File { char *val; int code; }File; File ibtab[] = { #include "btab" {nil, 0} }; File iwtab[] = { #include "wtab" {nil, 0} }; int binary(char *s) { int n; n = 0; while(*s) n = n*2 + *s++-'0'; return n; } void tabinit(File *file, Tab *tab) { int i, j, v, r, l; char *b; for(v=0; v<8192; v++) { tab[v].run = 0; tab[v].bits = 1; tab[v].code = ERR; } for(i=0; b=file[i].val; i++){ l = strlen(b); v = binary(b); r = file[i].code; if(l > 13) fprint(2, "g3: oops1 l = %d %s\n", l, b); v = v<<(13-l); for(j=0; j<(1<<((13-l))); j++) { if(tab[v].code != ERR) fprint(2, "g3: oops2 %d %s\n", r, b); tab[v].run = r; tab[v].bits = l; tab[v].code = TERM; if(r < 0) { tab[v].run = 0; tab[v].code = EOL; if(r < -1) { tab[v].bits = 1; tab[v].code = MAKE; } } if(r >= 64) { tab[v].code = MAKE; } v++; } } for(i=0; i<256; i++) for(j=0; j<8; j++) if(i & (1<> j; for(i=0; i<256; i++) bitnonrev[i] = i; } void initwbtab(void) { tabinit(iwtab, wtab); tabinit(ibtab, btab); }