Annotation of 43BSDReno/contrib/isode-beta/others/quipu/photo/decode.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.