1 #include <u.h> 2 #include <libc.h> 3 4 #define nil ((void*)0) 5 6 enum 7 { 8 ERR, 9 EOL, 10 MAKE, 11 TERM, 12 }; 13 14 enum 15 { 16 White, 17 Black, 18 }; 19 20 typedef struct Tab 21 { 22 ushort run; 23 ushort bits; 24 int code; 25 } Tab; 26 27 Tab wtab[8192]; 28 Tab btab[8192]; 29 uchar bitrev[256]; 30 uchar bitnonrev[256]; 31 32 int readrow(uchar *rev, int*); 33 void initwbtab(void); 34 void sync(uchar*); 35 int readfile(int, char*, char*); 36 37 int nbytes; 38 uchar *bytes; 39 uchar *pixels; 40 uchar *buf; 41 int y; 42 uint bitoffset; 43 uint word24; 44 45 enum 46 { 47 Bytes = 1024*1024, 48 Lines = 1410, /* 1100 for A4, 1410 for B4 */ 49 Dots = 1728, 50 }; 51 52 void 53 error(char *s, ...) 54 { 55 char buf[256]; 56 57 if(s){ 58 doprint(buf, buf+sizeof buf+1, s, &s+1); 59 fprint(2, "g3: %s\n", buf); 60 } 61 exits(s); 62 } 63 64 void 65 main(int argc, char **argv) 66 { 67 int y, fd, n; 68 char *t; 69 char *file, err[ERRLEN]; 70 71 if(argc > 2){ 72 fprint(2, "usage: g3out file\n"); 73 exits("usage"); 74 } 75 76 initwbtab(); 77 buf = malloc(1024*1024); 78 t = malloc(5*12+ (Dots/8)*Lines); 79 if(buf==nil || t==nil) 80 error("malloc failed: %r\n"); 81 pixels = (uchar*)t+(5*12); 82 83 file = "<stdin>"; 84 fd = 0; 85 if(argc > 1){ 86 file = argv[1]; 87 fd = open(file, OREAD); 88 if(fd < 0) 89 error("can't open %s", file); 90 } 91 y = readfile(fd, file, err); 92 if(y < 0) 93 error(err); 94 sprint(t, "%11d %11d %11d %11d %11d ", 0, 0, 0, Dots, y); 95 n = 5*12+(Dots/8)*y; 96 if(write(1, t, n) != n) 97 error("write error"); 98 if(err[0]) 99 error(err); 100 error(nil); 101 } 102 103 enum{ 104 Hvres, 105 Hbaud, 106 Hwidth, 107 Hlength, 108 Hcomp, 109 HenabECM, 110 HenabBFT, 111 Hmsperscan, 112 }; 113 114 int defhdr[8] = { 115 0, /* 98 lpi */ 116 0, /* 2400 baud */ 117 0, /* 1728 pixels in 215mm */ 118 0, /* A4, 297mm */ 119 0, /* 1-D modified huffman */ 120 0, /* disable ECM */ 121 0, /* disable BFT */ 122 3, /* 10 ms per scan */ 123 }; 124 125 int 126 crackhdr(uchar *ap, int *hdr) 127 { 128 char *p, *q; 129 int i; 130 131 p = (char*)ap; 132 q = p; 133 for(i=0; i<8; i++){ 134 if(*p<'0' || '9'<*p) 135 return -1; 136 hdr[i] = strtol(p, &q, 0); 137 p = q+1; 138 } 139 return p-(char*)ap; 140 } 141 142 int 143 readfile(int f, char *file, char *err) 144 { 145 int i, r, lines; 146 uchar *rev; 147 int hdr[8]; 148 149 err[0] = 0; 150 memset(pixels, 0, (Dots/8) * Lines); 151 nbytes = read(f, buf, 1024*1024); 152 close(f); 153 if(nbytes==1024*1024 || nbytes<=100){ 154 bad: 155 sprint(err, "g3: file improper size or format: %s", file); 156 return -1; 157 } 158 bytes = buf; 159 if(bytes[0]=='I' && bytes[1]=='I' && bytes[2]=='*'){ /* dumb PC format */ 160 bytes += 0xf3; 161 nbytes -= 0xf3; 162 rev = bitrev; 163 memmove(hdr, defhdr, sizeof defhdr); 164 }else{ 165 while(nbytes > 2){ 166 if(bytes[0]=='\n'){ 167 if(strncmp((char*)bytes+1, "FDCS=", 5) == 0){ 168 i = crackhdr(bytes+6, hdr); 169 if(i < 0){ 170 sprint(err, "g3: bad FDCS in header: %s", file); 171 return -1; 172 } 173 if(hdr[Hwidth] != 0){ 174 sprint(err, "g3: unsupported width: %s", file); 175 return -1; 176 } 177 if(hdr[Hcomp] != 0){ 178 sprint(err, "g3: unsupported compression: %s", file); 179 return -1; 180 } 181 bytes += i+1; 182 nbytes -= i+1; 183 continue; 184 } 185 if(bytes[1] == '\n'){ 186 bytes += 2; 187 nbytes -= 2; 188 break; 189 } 190 } 191 bytes++; 192 nbytes--; 193 } 194 if(nbytes < 2) 195 goto bad; 196 rev = bitnonrev; 197 } 198 bitoffset = 24; 199 word24 = 0; 200 sync(rev); 201 lines = Lines; 202 if(hdr[Hvres] == 1) 203 lines *= 2; 204 for(y=0; y<lines; y++){ 205 r = readrow(rev, hdr); 206 if(r < 0) 207 break; 208 if(r == 0) 209 sync(rev); 210 } 211 if(hdr[Hvres] == 1) 212 y /= 2; 213 if(y < 100) 214 goto bad; 215 return y; 216 } 217 218 int 219 readrow(uchar *rev, int *hdr) 220 { 221 int bo, state; 222 Tab *tab, *t; 223 int x, oldx, x2, oldx2, dx, xx; 224 uint w24; 225 uchar *p, *q; 226 227 state = White; 228 oldx = 0; 229 bo = bitoffset; 230 w24 = word24; 231 x = y; 232 if(hdr[Hvres] == 1) /* high resolution */ 233 x /= 2; 234 p = pixels + x*Dots/8; 235 x = 0; 236 237 loop: 238 if(x > Dots) 239 return 0; 240 if(state == White) 241 tab = wtab; 242 else 243 tab = btab; 244 if(bo > (24-13)) { 245 do { 246 if(nbytes <= 0) 247 return -1; 248 w24 = (w24<<8) | rev[*bytes]; 249 bo -= 8; 250 bytes++; 251 nbytes--; 252 } while(bo >= 8); 253 } 254 255 t = tab + ((w24 >> (24-13-bo)) & 8191); 256 x += t->run; 257 bo += t->bits; 258 if(t->code == TERM){ 259 if(state == White) 260 oldx = x; 261 else{ 262 oldx2 = oldx; 263 x2 = x; 264 xx = oldx2&7; 265 q = p+oldx2/8; 266 if(x2/8 == oldx2/8) /* all in one byte, but if((x2&7)==0), do harder case */ 267 *q |= (0xFF>>xx) & (0xFF<<(8-(x2&7))); 268 else{ 269 dx = x2 - oldx2; 270 /* leading edge */ 271 if(xx){ 272 *q++ |= 0xFF>>xx; 273 dx -= 8-xx; 274 } 275 /* middle */ 276 while(dx >= 8){ 277 *q++ = 0xFF; 278 dx -= 8; 279 } 280 /* trailing edge */ 281 if(dx) 282 *q |= 0xFF<<(8-dx); 283 } 284 } 285 state ^= White^Black; 286 goto loop; 287 } 288 if(t->code == ERR){ 289 bitoffset = bo; 290 word24 = w24; 291 return 0; 292 } 293 if(t->code == EOL){ 294 bitoffset = bo; 295 word24 = w24; 296 return 1; 297 } 298 goto loop; 299 return 0; 300 } 301 302 303 void 304 sync(uchar *rev) 305 { 306 Tab *t; 307 int c; 308 309 c = 0; 310 loop: 311 if(bitoffset > (24-13)) { 312 do { 313 if(nbytes <= 0) 314 return; 315 word24 = (word24<<8) | rev[*bytes]; 316 bitoffset -= 8; 317 bytes++; 318 nbytes--; 319 } while(bitoffset >= 8); 320 } 321 t = wtab + ((word24 >> (24-13-bitoffset)) & 8191); 322 if(t->code != EOL) { 323 bitoffset++; 324 c++; 325 goto loop; 326 } 327 bitoffset += t->bits; 328 } 329 330 typedef struct File 331 { 332 char *val; 333 int code; 334 }File; 335 336 File ibtab[] = { 337 #include "btab" 338 {nil, 0} 339 }; 340 341 File iwtab[] = { 342 #include "wtab" 343 {nil, 0} 344 }; 345 346 int 347 binary(char *s) 348 { 349 int n; 350 351 n = 0; 352 while(*s) 353 n = n*2 + *s++-'0'; 354 return n; 355 } 356 357 void 358 tabinit(File *file, Tab *tab) 359 { 360 int i, j, v, r, l; 361 char *b; 362 363 for(v=0; v<8192; v++) { 364 tab[v].run = 0; 365 tab[v].bits = 1; 366 tab[v].code = ERR; 367 } 368 for(i=0; b=file[i].val; i++){ 369 l = strlen(b); 370 v = binary(b); 371 r = file[i].code; 372 if(l > 13) 373 fprint(2, "g3: oops1 l = %d %s\n", l, b); 374 375 v = v<<(13-l); 376 for(j=0; j<(1<<((13-l))); j++) { 377 if(tab[v].code != ERR) 378 fprint(2, "g3: oops2 %d %s\n", r, b); 379 tab[v].run = r; 380 tab[v].bits = l; 381 tab[v].code = TERM; 382 if(r < 0) { 383 tab[v].run = 0; 384 tab[v].code = EOL; 385 if(r < -1) { 386 tab[v].bits = 1; 387 tab[v].code = MAKE; 388 } 389 } 390 if(r >= 64) { 391 tab[v].code = MAKE; 392 } 393 v++; 394 } 395 } 396 397 for(i=0; i<256; i++) 398 for(j=0; j<8; j++) 399 if(i & (1<<j)) 400 bitrev[i] |= 0x80 >> j; 401 for(i=0; i<256; i++) 402 bitnonrev[i] = i; 403 } 404 405 void 406 initwbtab(void) 407 { 408 tabinit(iwtab, wtab); 409 tabinit(ibtab, btab); 410 } 411