|
|
1.1 ! root 1: /* decode.c - the generic decoder */ ! 2: ! 3: #ifndef lint ! 4: static char *rcsid = "$Header: /f/osi/others/quipu/photo/RCS/decode.c,v 7.1 90/07/09 14:40:20 mrose Exp $"; ! 5: #endif ! 6: ! 7: /* ! 8: * $Header: /f/osi/others/quipu/photo/RCS/decode.c,v 7.1 90/07/09 14:40:20 mrose Exp $ ! 9: * ! 10: * ! 11: * $Log: decode.c,v $ ! 12: * Revision 7.1 90/07/09 14:40:20 mrose ! 13: * sync ! 14: * ! 15: * Revision 7.0 89/11/23 22:01:37 mrose ! 16: * Release 6.0 ! 17: * ! 18: */ ! 19: ! 20: /* ! 21: * NOTICE ! 22: * ! 23: * Acquisition, use, and distribution of this module and related ! 24: * materials are subject to the restrictions of a license agreement. ! 25: * Consult the Preface in the User's Manual for the full terms of ! 26: * this agreement. ! 27: * ! 28: */ ! 29: ! 30: ! 31: ! 32: #include <stdio.h> ! 33: #include <sgtty.h> ! 34: #include <signal.h> ! 35: #include "quipu/photo.h" ! 36: ! 37: #define ERR_RUN 0x0f ! 38: ! 39: #ifdef lint ! 40: #define FAXDIR "/tmp" ! 41: #endif ! 42: ! 43: /* this file contains the main routines for decoding X400 */ ! 44: ! 45: extern int PIC_LINESIZE,STOP,NUMLINES; ! 46: ! 47: /* variables for top of the code word trees */ ! 48: node * bl_tree_top; ! 49: node * wt_tree_top; ! 50: node * two_tree_top; ! 51: ! 52: unsigned int position; ! 53: ! 54: static char ref_colour; ! 55: static char colour; ! 56: char * malloc (); ! 57: char *bitmap; ! 58: ! 59: /* ROUTINE: Decode_t4 ! 60: /* ! 61: /* SYNOPSIS: Decodes a bit map stored in format T4 as recommended ! 62: /* by CCITT. ! 63: /* ! 64: /* DESCRIPTION: After setting up the buffers, a line at a time is dealt with. ! 65: /* Each line is recognised as being one or two dimensionally coded, depending ! 66: /* upon the tag bit. ! 67: /* The run change buffers for each line are kept incase the next line is two ! 68: /* dimensionally, when it will be used as a reference. ! 69: /* ! 70: */ ! 71: ! 72: int decode_t4 (inbuf, winname, length) ! 73: char *inbuf, *winname; ! 74: int length; ! 75: { ! 76: bit_string code_line, /* output line */ ! 77: ref_line, /* reference line */ ! 78: t4_line; /* input line */ ! 79: ! 80: int done = 0; ! 81: run_type run; ! 82: ! 83: int *buffer1, *buffer2; ! 84: int *run_buf1, *run_buf2; ! 85: char tag,nextbit; ! 86: ! 87: if (photo_start (winname) == -1) ! 88: return (-1); ! 89: ! 90: if (build_trees (FAXDIR) == -1) ! 91: return (-1); ! 92: ! 93: buffer1 = (int *) malloc (LINEBUF * sizeof(int)); ! 94: buffer2 = (int *) malloc (LINEBUF * sizeof(int)); ! 95: buffer1[0] = 0; /* to halt backtracting if needed at start of line */ ! 96: buffer2[0] = 0; ! 97: run_buf1 = buffer1; ! 98: run_buf2 = buffer2; ! 99: ref_line.run_top = ++run_buf1; ! 100: code_line.run_top = ++run_buf2; ! 101: ! 102: code_line.dbuf_top = malloc (BUFSIZ); ! 103: t4_line.dbuf_top = inbuf; ! 104: ! 105: if (set_dinput (&t4_line, length) == -1) ! 106: return (-1); ! 107: set_doutput (&code_line); ! 108: ! 109: /* t4 starts with an initial end of line */ ! 110: run = next_run(&t4_line,WHITE); ! 111: if (run.r_type == ERR_RUN) ! 112: return (-1); ! 113: if (run.r_type != EOLN) { ! 114: (void) fprintf (stderr,"PHOTO: Initial end of line missing"); ! 115: return (-1); ! 116: } ! 117: if ( get_bit(&t4_line) != 1){ ! 118: (void) fprintf (stderr,"PHOTO: Initial end of line (2) missing"); ! 119: return (-1); ! 120: } ! 121: ! 122: NUMLINES = -1; ! 123: ! 124: tag = nextbit = get_bit(&t4_line); ! 125: ! 126: do { ! 127: NUMLINES++; ! 128: ! 129: position = 1; ! 130: if (nextbit != tag ) ! 131: { if (code_line.run_top == run_buf1) ! 132: { ref_line.run_top = run_buf1; ! 133: code_line.run_top = run_buf2; ! 134: } ! 135: else ! 136: { ref_line.run_top = run_buf2; ! 137: code_line.run_top = run_buf1; ! 138: } ! 139: done = decode_two (&ref_line,&code_line,&t4_line); ! 140: } ! 141: else ! 142: { code_line.run_pos = code_line.run_top; ! 143: done = decode_one (&code_line,&t4_line); ! 144: } ! 145: ! 146: if (done == -1) ! 147: return (-1); ! 148: ! 149: flush_doutput (&code_line); ! 150: set_doutput (&code_line); ! 151: ! 152: photo_line_end (&code_line); ! 153: ! 154: if (!done) ! 155: nextbit = get_bit(&t4_line); ! 156: ! 157: } while (! done); ! 158: ! 159: flush_doutput (&code_line); ! 160: bitmap = code_line.dbuf_top; ! 161: ! 162: (void) free ( (char *)buffer1); ! 163: (void) free ( (char *)buffer2); ! 164: ! 165: return (photo_end (winname)); ! 166: ! 167: } ! 168: ! 169: ! 170: ! 171: /* ROUTINE: next_run ! 172: * ! 173: * SYNOPSIS: Reads the next run length from the input file. ! 174: * ! 175: * DESCRIPTION: As each bit is read, it is used to move down the decode tree, ! 176: * when a node is found that contains a value, the value is returned. ! 177: * The code is assumed to be one dimensional. ! 178: */ ! 179: ! 180: run_type ! 181: next_run (lineptr,xcolour) ! 182: bit_string * lineptr; ! 183: char xcolour; ! 184: { ! 185: ! 186: node * ptr; ! 187: run_type result ; ! 188: result.run_length = 0; ! 189: ! 190: if (xcolour == BLACK) { ! 191: ptr = bl_tree_top; ! 192: } else { ! 193: ptr = wt_tree_top; ! 194: } ! 195: ! 196: if (ptr == NULL) { ! 197: (void) fprintf (stderr,"PHOTO: tree error"); ! 198: result.r_type = ERR_RUN; ! 199: return (result); ! 200: } ! 201: ! 202: do { ! 203: ! 204: if (get_bit (lineptr) == 0) ! 205: ptr = ptr->zero; ! 206: else ! 207: ptr = ptr->one; ! 208: ! 209: if (ptr == NULL) { ! 210: /* it may be possible to recover from this in the future */ ! 211: (void) fprintf (stderr,"PHOTO: Sequencing error (1)"); ! 212: result.r_type = ERR_RUN; ! 213: return (result); ! 214: } ! 215: ! 216: } while (ptr->n_type == INTERNAL); ! 217: ! 218: /* if the above value was a make up code, now read the terminal code */ ! 219: if (ptr->n_type == MAKE) { ! 220: result.run_length = ptr->value; ! 221: if (xcolour == BLACK) { ! 222: ptr = bl_tree_top; ! 223: } else { ! 224: ptr = wt_tree_top; ! 225: } ! 226: ! 227: if (ptr == NULL) { ! 228: (void) fprintf (stderr,"PHOTO: tree error"); ! 229: result.r_type = ERR_RUN; ! 230: return (result); ! 231: } ! 232: ! 233: do { ! 234: ! 235: if (get_bit (lineptr) == 0) { ! 236: ptr = ptr->zero; ! 237: } else { ! 238: ptr = ptr->one; ! 239: } ! 240: ! 241: if (ptr == NULL) { ! 242: /* it may be possible to recover from this ! */ ! 243: (void) fprintf (stderr,"PHOTO: Sequencing error (2)"); ! 244: result.r_type = ERR_RUN; ! 245: return (result); ! 246: } ! 247: } while (ptr->n_type == INTERNAL); ! 248: ! 249: } ! 250: ! 251: result.run_length += ptr->value; ! 252: result.r_type = ptr->n_type; ! 253: return (result); ! 254: ! 255: } ! 256: ! 257: ! 258: ! 259: /* ROUTINE: decode_one ! 260: /* ! 261: /* SYNOPSIS: decodes one line of t4. ! 262: /* ! 263: /* DESCRIPTION: reads a run, then writes that many bit of the appropiate ! 264: /* colour to the output. ! 265: */ ! 266: ! 267: decode_one (lineptr, t4_lineptr) ! 268: bit_string * lineptr; ! 269: bit_string * t4_lineptr; ! 270: ! 271: { ! 272: run_type run; ! 273: char xcolour = WHITE; ! 274: int done; ! 275: int savelinesize; ! 276: ! 277: savelinesize = PIC_LINESIZE; ! 278: PIC_LINESIZE = 0; ! 279: run = next_run (t4_lineptr,xcolour); ! 280: if (run.r_type == ERR_RUN) ! 281: return (-1); ! 282: ! 283: while (run.r_type != EOLN) { ! 284: PIC_LINESIZE += run.run_length; ! 285: put_run (lineptr,run.run_length,xcolour); ! 286: xcolour = 1 - xcolour; ! 287: run = next_run (t4_lineptr,xcolour); ! 288: if (run.r_type == ERR_RUN) ! 289: return (-1); ! 290: } ! 291: while (get_bit(t4_lineptr) != 01) ! 292: ; /* skip fill characters */ ! 293: ! 294: if (lineptr->run_pos == lineptr->run_top){ ! 295: done = 1; ! 296: PIC_LINESIZE = savelinesize; ! 297: } else ! 298: done = 0; ! 299: ! 300: STOP = PIC_LINESIZE + 1; ! 301: *(lineptr->run_pos++) = STOP; ! 302: *(lineptr->run_pos) = STOP; ! 303: ! 304: return (done); ! 305: } ! 306: ! 307: ! 308: ! 309: /* ROUTINE: decode_two ! 310: /* ! 311: /* SYNOPSIS: decodes a two dim line. ! 312: /* ! 313: /* DESCRIPTION: The binary codes read in are looked up in the decode tree, ! 314: /* and the appropiate routine called to decode that mode. ! 315: */ ! 316: ! 317: decode_two (ref_lineptr,code_lineptr,t4_lineptr) ! 318: ! 319: bit_string * ref_lineptr; ! 320: bit_string * code_lineptr; ! 321: bit_string * t4_lineptr; ! 322: ! 323: { ! 324: node * ptr; ! 325: int done; ! 326: ! 327: ref_lineptr->run_pos = ref_lineptr->run_top; ! 328: code_lineptr->run_pos = code_lineptr->run_top; ! 329: colour = WHITE; ! 330: ref_colour = BLACK; ! 331: do { ! 332: ptr = two_tree_top; ! 333: do { ! 334: if (ptr == NULL) { ! 335: (void) fprintf (stderr,"PHOTO: 2-d line failure"); ! 336: return (-1); ! 337: } ! 338: ! 339: if (get_bit (t4_lineptr) == 0) ! 340: ptr = ptr->zero; ! 341: else ! 342: ptr = ptr->one; ! 343: } while (ptr->n_type == INTERNAL); ! 344: ! 345: switch (ptr->value) { ! 346: ! 347: case P: undo_pass_mode (ref_lineptr,code_lineptr); ! 348: break; ! 349: ! 350: case H: if (undo_horiz_mode (t4_lineptr,code_lineptr) == -1) ! 351: return (-1); ! 352: break; ! 353: ! 354: case EOLN: break; ! 355: ! 356: default: undo_vert_mode (ref_lineptr,code_lineptr,ptr->value); ! 357: ! 358: } ! 359: ! 360: } while (ptr->n_type != EOLN ); ! 361: ! 362: /* fill to end of line with current colour */ ! 363: put_run (code_lineptr,(int)( PIC_LINESIZE - position + 1 ), colour); ! 364: ! 365: if (code_lineptr->run_pos == code_lineptr->run_top) /* no runs found */ ! 366: done = 1; ! 367: else ! 368: done = 0; ! 369: ! 370: while (get_bit (t4_lineptr) != 1) ! 371: ; /* skip fill characters */ ! 372: ! 373: *(code_lineptr->run_pos++) = STOP; ! 374: *(code_lineptr->run_pos) = STOP; ! 375: ! 376: return (done); ! 377: } ! 378: ! 379: ! 380: /* ROUTINE: undo_pass_mode ! 381: /* ! 382: /* SYNOPSIS: decodes a section recognised as pass mode. ! 383: /* ! 384: /* DESCRIPTION: find b2, then write to output the same colour as before ! 385: /* up until position b2. ! 386: */ ! 387: ! 388: undo_pass_mode (ref_lineptr,code_lineptr) ! 389: bit_string * ref_lineptr; ! 390: bit_string * code_lineptr; ! 391: ! 392: { ! 393: goto_b1 (ref_lineptr); ! 394: ! 395: ref_lineptr->run_pos++; ! 396: ref_colour = 1 - ref_colour; ! 397: ! 398: put_run (code_lineptr,(int) (*(ref_lineptr->run_pos) - position), colour); ! 399: code_lineptr->run_pos--; /* don't count this as a change */ ! 400: } ! 401: ! 402: ! 403: ! 404: ! 405: /* ROUTINE: undo_horiz_mode ! 406: /* ! 407: /* SYNOPSIS: decodes a section recognised as horizontal mode. ! 408: /* ! 409: /* DESCRIPTION: Read two run lengths for the input, and write the appropiate ! 410: /* number of 1's or 0's to the output. ! 411: */ ! 412: ! 413: undo_horiz_mode (t4_lineptr,code_lineptr) ! 414: ! 415: bit_string * t4_lineptr; ! 416: bit_string * code_lineptr; ! 417: ! 418: { ! 419: run_type run; ! 420: ! 421: run = next_run (t4_lineptr,colour); ! 422: if (run.r_type == ERR_RUN) ! 423: return (-1); ! 424: put_run (code_lineptr,run.run_length,colour); ! 425: ! 426: run = next_run (t4_lineptr,1-colour); ! 427: if (run.r_type == ERR_RUN) ! 428: return (-1); ! 429: put_run (code_lineptr,run.run_length,1-colour); ! 430: ! 431: return (0); ! 432: } ! 433: ! 434: ! 435: /* ROUTINE: undo_vert_mode ! 436: /* ! 437: /* SYNOPSIS: decodes vertical mode ! 438: /* ! 439: /* DESCRIPTION: Find b1, the write 1's or 0's upto it allowing for the offset. ! 440: */ ! 441: ! 442: undo_vert_mode (ref_lineptr,code_lineptr,offset) ! 443: ! 444: bit_string * ref_lineptr; ! 445: bit_string * code_lineptr; ! 446: char offset; ! 447: ! 448: { ! 449: int length; ! 450: ! 451: /* find b1 */ ! 452: goto_b1 (ref_lineptr); ! 453: ! 454: length = (*ref_lineptr->run_pos - position) + offset - FIXED_OFFSET; ! 455: put_run ( code_lineptr, length , colour); ! 456: colour = 1 - colour; ! 457: } ! 458: ! 459: /* ROUTINE: goto_b1 ! 460: * ! 461: * SYNOPSIS: move the pointer in the reference line to b1 ! 462: * ! 463: * DESCRIPTION: b1 is the first changing bit in the reference line ! 464: * of a different colour to a0. May need to move backwards or forwards ! 465: * ! 466: */ ! 467: ! 468: goto_b1 (lineptr) ! 469: bit_string * lineptr; ! 470: ! 471: { ! 472: ! 473: if ( *lineptr->run_pos > position ) ! 474: do ! 475: ref_colour = 1 - ref_colour; ! 476: while ( *--lineptr->run_pos > position ) ; ! 477: ! 478: if ( *lineptr->run_pos < position ) ! 479: do ! 480: ref_colour = 1 - ref_colour; ! 481: while ( *++lineptr->run_pos < position ) ; ! 482: ! 483: if (ref_colour == colour) { ! 484: lineptr->run_pos++; ! 485: ref_colour = 1 - ref_colour; ! 486: ! 487: } else ! 488: /* special case when b1 = a0, and the colours are different, ! 489: move b1 to the next change of same colour, ! 490: this must be allowed at the beginning of a line to get a run of ! 491: zero, as every line must start with a white element */ ! 492: if ((*lineptr->run_pos == position) && (*lineptr->run_pos >1 )) { ! 493: lineptr->run_pos++; ! 494: lineptr->run_pos++; ! 495: } ! 496: ! 497: } ! 498: ! 499: ! 500: /* ROUTINE: put_run */ ! 501: /* */ ! 502: /* SYNOPSIS: writes a run_length to the indiacated bit_string, */ ! 503: /* */ ! 504: ! 505: put_run (lineptr, length, xcolour) ! 506: bit_string * lineptr; ! 507: int length; ! 508: char xcolour; ! 509: { ! 510: register i; ! 511: ! 512: if ( xcolour == WHITE) ! 513: photo_white (length); ! 514: else ! 515: photo_black (length); ! 516: ! 517: /* now fill line buffer for purpose of decoding 2-d lines */ ! 518: ! 519: if (length > 16) ! 520: { position += length; ! 521: *lineptr->run_pos++ = position; ! 522: ! 523: if (lineptr->mask != BIT_MASK) { /* fill current byte */ ! 524: if (xcolour == WHITE) ! 525: do { ! 526: clr_bit (lineptr); ! 527: length--; ! 528: } while (lineptr->mask != BIT_MASK); ! 529: ! 530: else ! 531: do { ! 532: set_bit (lineptr); ! 533: length--; ! 534: } while (lineptr->mask != BIT_MASK); ! 535: } ! 536: ! 537: /* write out the bytes */ ! 538: if (xcolour == WHITE) ! 539: for (i=0; i<length/8; i++) ! 540: *lineptr->dbuf++ = 0; ! 541: else ! 542: for (i=0; i<length/8; i++) ! 543: *lineptr->dbuf++ = 0xff; ! 544: ! 545: ! 546: /* put the last few bits into the next byte */ ! 547: if (xcolour == WHITE) ! 548: for (i=0; i<length%8; i++) ! 549: clr_bit (lineptr); ! 550: else ! 551: for (i=0; i<length%8; i++) ! 552: set_bit (lineptr); ! 553: } ! 554: else ! 555: { /* length < 16 - can't optimise, so deal with bits */ ! 556: ! 557: if (xcolour == WHITE) { ! 558: for (i=0; i<length; i++) clr_bit (lineptr); ! 559: position += length; ! 560: *lineptr->run_pos++ = position; ! 561: } else { ! 562: for (i=0; i<length; i++) ! 563: set_bit (lineptr); ! 564: position += length; ! 565: *lineptr->run_pos++ = position; ! 566: } ! 567: ! 568: } ! 569: ! 570: } ! 571: ! 572: /* ROUTINE: set_doutput; ! 573: /* ! 574: /* SYNOPSIS: Initialises the output buffers ! 575: */ ! 576: ! 577: set_doutput (lineptr) ! 578: bit_string * lineptr; ! 579: { ! 580: lineptr->dbuf = lineptr->dbuf_top; ! 581: lineptr->mask = BIT_MASK; ! 582: } ! 583: ! 584: ! 585: ! 586: ! 587: /* ROUTINE: flush_doutput; ! 588: /* ! 589: /* SYNOPSIS: flush the output buffer; ! 590: */ ! 591: ! 592: flush_doutput (lineptr) ! 593: bit_string * lineptr; ! 594: { ! 595: int count = 0; ! 596: ! 597: while ( lineptr->mask != BIT_MASK ) { ! 598: clr_bit (lineptr); ! 599: count++; ! 600: } ! 601: photo_white (count); ! 602: } ! 603: ! 604: ! 605: ! 606: /* ROUTINE: set_dinput; ! 607: /* ! 608: /* SYNOPSIS: Initialises the input buffers ! 609: */ ! 610: ! 611: set_dinput (lineptr, length) ! 612: bit_string * lineptr; ! 613: int length; ! 614: { ! 615: bit_string temp; ! 616: int i; ! 617: ! 618: lineptr->dbuf = lineptr->dbuf_top; ! 619: ! 620: if (length == 0) { ! 621: /* check id + skip length */ ! 622: if ( *lineptr->dbuf++ != 0x03 ) { ! 623: (void) fprintf (stderr,"PHOTO: Not a g3fax bit map"); ! 624: return (-1); ! 625: } ! 626: ! 627: if ((length = piclen (lineptr->dbuf_top)) == -1) ! 628: return (-1); ! 629: } ! 630: ! 631: while ((lineptr->pos = *lineptr->dbuf++) != 0x00) ! 632: ; /* no op */ ! 633: ! 634: lineptr->mask = BIT_MASK; ! 635: ! 636: return (0); ! 637: } ! 638: ! 639: piclen (s1) ! 640: char * s1; ! 641: { ! 642: int length=0,cnt,i; ! 643: char * temp; ! 644: ! 645: if (*s1 == 0x03) { ! 646: /* we have a coded picture */ ! 647: ! 648: temp = s1; ! 649: temp++; ! 650: cnt = *temp++ & 0x7f; /*assume len > 127 for now */ ! 651: for (i=0; i<cnt; i++) ! 652: length = (length << 8) | (*temp++ & 0xff) ; ! 653: ! 654: length += 2 + cnt; ! 655: return (length); ! 656: ! 657: } else { ! 658: (void) fprintf (stderr,"PHOTO: length error"); ! 659: return (-1); ! 660: } ! 661: ! 662: } ! 663:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.