123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456 |
- #include <u.h>
- #include <libc.h>
- 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 = "<stdin>";
- 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<yscale; y++){
- if(write(1, t, m) != m)
- error("write error");
- n -= m;
- }
- t += m;
- }
- if(err[0])
- error(err);
- error(nil);
- }
- enum{
- Hvres,
- Hbaud,
- Hwidth,
- Hlength,
- Hcomp,
- HenabECM,
- HenabBFT,
- Hmsperscan,
- };
- int defhdr[8] = {
- 0, /* 98 lpi */
- 0, /* 2400 baud */
- 0, /* 1728 pixels in 215mm */
- 0, /* A4, 297mm */
- 0, /* 1-D modified huffman */
- 0, /* disable ECM */
- 0, /* disable BFT */
- 3, /* 10 ms per scan */
- };
- int
- crackhdr(uchar *ap, int *hdr)
- {
- char *p, *q;
- int i;
- p = (char*)ap;
- q = p;
- for(i=0; i<8; i++){
- if(*p<'0' || '9'<*p)
- return -1;
- hdr[i] = strtol(p, &q, 0);
- p = q+1;
- }
- return p-(char*)ap;
- }
- int
- readfile(int f, char *file, char *err)
- {
- int i, r, lines;
- uchar *rev;
- int hdr[8];
- err[0] = 0;
- memset(pixels, 0, (Dots/8) * Lines);
- nbytes = readn(f, buf, 1024*1024);
- if(nbytes==1024*1024 || nbytes<=100){
- bad:
- sprint(err, "g3: file improper size or format: %s", file);
- return -1;
- }
- bytes = buf;
- if(bytes[0]=='I' && bytes[1]=='I' && bytes[2]=='*'){ /* dumb PC format */
- bytes += 0xf3;
- nbytes -= 0xf3;
- rev = bitrev;
- memmove(hdr, defhdr, sizeof defhdr);
- }else if(bytes[0] == 0 && strcmp((char*)bytes+1, "PC Research, Inc") == 0){ /* digifax format */
- memmove(hdr, defhdr, sizeof defhdr);
- if(bytes[45] == 0x40 && bytes[29] == 1) /* high resolution */
- hdr[Hvres] = 1;
- else
- hdr[Hvres] = 0;
- /* hdr[26] | (hdr[27]<<8) is page number */
- bytes += 64;
- nbytes -= 64;
- rev = bitnonrev;
- }else{
- while(nbytes > 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<lines; y++){
- r = readrow(rev, hdr);
- if(r < 0)
- break;
- if(r == 0)
- sync(rev);
- }
- if(hdr[Hvres] == 1)
- y /= 2;
- // if(y < 100)
- // goto bad;
- return y;
- }
- int
- readrow(uchar *rev, int *hdr)
- {
- int bo, state;
- Tab *tab, *t;
- int x, oldx, x2, oldx2, dx, xx;
- uint w24;
- uchar *p, *q;
- state = White;
- oldx = 0;
- bo = bitoffset;
- w24 = word24;
- x = y;
- if(hdr[Hvres] == 1) /* high resolution */
- x /= 2;
- p = pixels + x*Dots/8;
- x = 0;
- loop:
- if(x > 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;
- return 0;
- }
- 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))
- bitrev[i] |= 0x80 >> j;
- for(i=0; i<256; i++)
- bitnonrev[i] = i;
- }
- void
- initwbtab(void)
- {
- tabinit(iwtab, wtab);
- tabinit(ibtab, btab);
- }
|