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

1.1       root        1: /* encode.c - implement encoding routines */
                      2: 
                      3: #ifndef        lint
                      4: static char *rcsid = "$Header: /f/osi/others/quipu/photo/RCS/encode.c,v 7.1 90/07/09 14:40:25 mrose Exp $";
                      5: #endif
                      6: 
                      7: /* 
                      8:  * $Header: /f/osi/others/quipu/photo/RCS/encode.c,v 7.1 90/07/09 14:40:25 mrose Exp $
                      9:  *
                     10:  *
                     11:  * $Log:       encode.c,v $
                     12:  * Revision 7.1  90/07/09  14:40:25  mrose
                     13:  * sync
                     14:  * 
                     15:  * Revision 7.0  89/11/23  22:01:39  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 "quipu/photo.h"
                     34: 
                     35: extern int PIC_LINESIZE,STOP,NUMLINES;
                     36: 
                     37: int a0, a1, b1, b2;             /* markers */
                     38: int optlen;
                     39: 
                     40: char * malloc();
                     41: 
                     42: 
                     43: /* ROUTINE:     encode_t4
                     44: /*
                     45: /* SYNOPSIS:    Implements CCITT recommendation T.4.
                     46: /*              This recomendation is concerned with compressing of bit maps.
                     47: /*
                     48: /* DESCRIPTION:
                     49: /*              This routine sets up the data buffers, then calls routines
                     50: /* to encode one line of the bit map. A line can be encoded  either one
                     51: /* dimensionally  or two dimensionally depending upon the 'k parameter'.
                     52: /*    When a line is encode two dimensionally, the line before is used as a
                     53: /* reference. For each line encoded a record of where the run changes occur
                     54: /* are kept. this is the used as the reference.
                     55: /*
                     56: */
                     57: 
                     58: 
                     59: char * encode_t4 (k_param,inbuf, eolnskip)
                     60: int     k_param;
                     61: char *  inbuf;
                     62: int eolnskip;
                     63: 
                     64: {
                     65: bit_string ref_line;            /* Reference line */
                     66: bit_string t4_line;             /* Output encoded line */
                     67: bit_string code_line;           /* Line we are codeing  */
                     68: 
                     69: short   i,j;                      /* Loop variable */
                     70: int    run_buf [LINEBUF], run_buf2 [LINEBUF];
                     71: 
                     72: 
                     73:    ref_line.run_top = run_buf;
                     74:    code_line.run_top = run_buf2;
                     75:    
                     76:    code_line.dbuf_top = inbuf;
                     77:    t4_line.dbuf_top = malloc (PIC_LINESIZE * NUMLINES);
                     78: 
                     79:    set_input  (&code_line);
                     80:    set_output (&t4_line);
                     81: 
                     82:    /* Repeat this loop once for every input line expected */
                     83:    for (i=0; i< NUMLINES; i++) {
                     84: 
                     85:        put_eoln (&t4_line);                     /* eoln marker before each new data line */
                     86:        if (code_line.run_top == run_buf) { /*swap buffers*/
                     87:                        ref_line.run_top = run_buf;
                     88:                        code_line.run_top = run_buf2;
                     89:                } else {
                     90:                        ref_line.run_top = run_buf2;
                     91:                        code_line.run_top = run_buf;
                     92:                }
                     93:                
                     94:        /* reset pointers */
                     95:        code_line.run_pos  = code_line.run_top;
                     96:        ref_line.run_pos  = ref_line.run_top;
                     97:        
                     98:        /* fill buffer for coding line */
                     99:        
                    100:        get_runs (&code_line);
                    101:        code_line.run_pos  = code_line.run_top;
                    102: 
                    103:        if (i % k_param == 0) {
                    104:          set_bit (&t4_line);                   /* tag bit, 1-d line follows */
                    105:          code_one (&code_line,&t4_line);
                    106: 
                    107:        } else {
                    108:          clr_bit (&t4_line);                   /* tag bit, 2-d line follows */
                    109:          code_two (&ref_line,&code_line,&t4_line);
                    110:        }
                    111:        /* skip any extra eoln bit in orig data */
                    112:        for (j=0;j<eolnskip;j++)
                    113:                get_bit (&code_line);
                    114: 
                    115:    }
                    116:    /* now finish as per X409 */
                    117:    put_eoln (&t4_line);
                    118:    set_bit (&t4_line);
                    119:    put_eoln (&t4_line);
                    120:    set_bit (&t4_line);
                    121:    put_eoln (&t4_line);
                    122:    set_bit (&t4_line);
                    123:    put_eoln (&t4_line);
                    124:    set_bit (&t4_line);
                    125:    put_eoln (&t4_line);
                    126:    set_bit (&t4_line);
                    127:    put_eoln (&t4_line);
                    128:    set_bit (&t4_line);
                    129:    
                    130:    /* flush buffers, write length */
                    131:    flush_output (&t4_line);
                    132:    return (t4_line.dbuf_top);
                    133: }
                    134: 
                    135: 
                    136: 
                    137: /* ROUTINE:     code_one
                    138: /*
                    139: /* SYNOPSIS:    codes one line of a bit map into t4
                    140: /*
                    141: /* DESCRIPTION:
                    142: /*              To encode a line one dimensionally, bits are read in until
                    143: /* a change is noticed, when this happens, the run_length code for the number
                    144: /* of bits read in is found, and written to the output file.
                    145: /* A run_length code may consist of two parts if the run is large, a make up
                    146: /* and a terminal code.
                    147: */
                    148: 
                    149: code_one (lineptr,t4_lineptr)
                    150: 
                    151: bit_string * lineptr;           /* input line */
                    152: bit_string * t4_lineptr;        /* output line */
                    153: 
                    154: {
                    155: char            colour = WHITE; /* the colour of the current bit */
                    156: full_code       code;           /* the code for the characters run_length */
                    157: int             old_pos = 1;    /* the number of bits of the same colur read in */
                    158: 
                    159: 
                    160:        do {
                    161:           /* get code for next run = pos of current change - pos of last change */
                    162:           code = get_code (*++lineptr->run_pos - old_pos,colour);
                    163: 
                    164:           if (code.make.length != 0)
                    165:              put_code (t4_lineptr,code.make);          /* the make code */
                    166:           put_code (t4_lineptr, code.term);            /* the terminal code */
                    167:           colour = 1 - colour;
                    168:           old_pos =  *lineptr->run_pos;
                    169: 
                    170:        } while (*lineptr->run_pos <= PIC_LINESIZE);
                    171: }
                    172: 
                    173: 
                    174: 
                    175: 
                    176: 
                    177: 
                    178: /* ROUTINE:     code_two
                    179: /*
                    180: /* SYNOPSIS:    Codes one line of a bit map two dimensionally as
                    181: /*              described by CCITT T.4.
                    182: /*
                    183: /* DESCRIPTION: Two lines are compared by looking at the list of run changes.
                    184: /* In order to do this, this list has to be created for the line we are about
                    185: /* to encode.  The encoding procedure then follows the flow chart in the CCITT
                    186: /* recommendation.
                    187: /* That is summarised as follows, find the positions a0,a1,b1,b2, the compare
                    188: /* the to see which mode is required.  The positions of a1,b1,b2 are found from
                    189: /* the run change list.  a0 is known in advance.
                    190: */
                    191: 
                    192: code_two (ref_lineptr,code_lineptr,t4_lineptr)
                    193: 
                    194: bit_string * ref_lineptr;       /* reference line */
                    195: bit_string * code_lineptr;      /* line to encode */
                    196: bit_string * t4_lineptr;        /* output line    */
                    197: 
                    198: {
                    199: char    colour = WHITE;
                    200: char    ref_colour = WHITE;
                    201: 
                    202:    a0 = 0;
                    203:    code_lineptr->run_pos = code_lineptr->run_top;
                    204: 
                    205:    do {
                    206:        /* move all pointers to be level with a0 to start keeping colour    */
                    207:        /* variables up to date.  Move past a0, then move back, this ensures*/
                    208:        /* we are at the change immediately before a0 */
                    209: 
                    210:        if  ( *(code_lineptr->run_pos)  > a0)
                    211:          while ( *(--code_lineptr->run_pos) > a0 )
                    212:                ;
                    213: 
                    214:        if ( *ref_lineptr->run_pos < a0 )
                    215:         do
                    216:            ref_colour = 1 - ref_colour;
                    217:         while (*++ref_lineptr->run_pos < a0) ;
                    218: 
                    219:        if  ( *(ref_lineptr->run_pos)  > a0)
                    220:          do
                    221:              ref_colour = 1-ref_colour;
                    222:          while ( *(--ref_lineptr->run_pos) > a0 ) ;
                    223: 
                    224:        /* find a1 */
                    225:        a1 = *(++code_lineptr->run_pos);
                    226:        if (a1 >= STOP)
                    227:           code_lineptr->run_pos--;
                    228: 
                    229:        if (ref_colour != colour) {
                    230:          ref_lineptr->run_pos++;
                    231:          ref_colour = 1 - ref_colour;
                    232:        }
                    233: 
                    234:        /* find b1 */
                    235:        b1 = *(++ref_lineptr->run_pos);
                    236:        if (b1 >= STOP) {
                    237:           ref_lineptr->run_pos--;
                    238:           ref_colour = 1 - ref_colour;
                    239:           b2 = STOP;
                    240: 
                    241:        } else {
                    242:           /* find b2 */
                    243:           b2 = *(++ref_lineptr->run_pos);
                    244:           if (b2 >= STOP) {
                    245:               ref_lineptr->run_pos--;
                    246:               ref_colour = 1 - ref_colour;
                    247:           }
                    248:        }
                    249: 
                    250:        /* select mode and code it */
                    251:     if (a1 >= STOP) {
                    252:           a0=STOP;     /* to stop loop */
                    253:           }
                    254:     else {
                    255:        if (a1 > b2)
                    256:          pass_mode (t4_lineptr);
                    257: 
                    258:        else {
                    259:          if (abs (a1-b1) <= 3) {
                    260:             vertical_mode (t4_lineptr);
                    261:             colour = 1 - colour;
                    262: 
                    263:          } else
                    264:             horizontal_mode (code_lineptr,t4_lineptr,colour);
                    265:        }
                    266:     }
                    267:    } while (a0 < STOP );
                    268: 
                    269: }
                    270: 
                    271: 
                    272: /* ROUTINE:     Pass_mode
                    273: /*
                    274: /* SYNOPSIS:    Encodes pass_mode
                    275: /*
                    276: /* DESCRIPTION: When pass mode is detected, the pass mode code is written to
                    277: /* the output, and a0 is moved to underneath b2.
                    278: */
                    279: 
                    280: pass_mode (t4_lineptr)
                    281: bit_string * t4_lineptr;
                    282: 
                    283: {
                    284: static code_word code = {4,0x0200};
                    285:    put_code (t4_lineptr,code);
                    286:    a0 = b2;
                    287: }
                    288: 
                    289: 
                    290: /* ROUTINE:     Vertical_mode
                    291: /*
                    292: /* SYNOPSIS:    Encodes vertical mode.
                    293: /*
                    294: /* DESCRIPTION:  Vertical mode is encoded by writing a particualr code
                    295: /* depending on the offset between a1 and b1.
                    296: /* a0 is moved to a1
                    297: */
                    298: 
                    299: vertical_mode (t4_lineptr)
                    300: 
                    301: bit_string * t4_lineptr;
                    302: 
                    303: {
                    304: static code_word code [7] = {
                    305:        {7,0x080  },    /* -3 */
                    306:        {6,0x100  },    /* -2 */
                    307:        {3,0x800  },    /* -1 */
                    308:        {1,0x1000 },    /*  0 */
                    309:        {3,0xc00  },    /*  1 */
                    310:        {6,0x180  },    /*  2 */
                    311:        {7,0xc0   },    /*  3 */
                    312:    };
                    313:    put_code (t4_lineptr, code [a1-b1+3]);
                    314: 
                    315:    a0 = a1;
                    316: }
                    317: 
                    318: 
                    319: 
                    320: 
                    321: /* ROUTINE:     Horizontal_mode
                    322: /*
                    323: /* SYNOPSIS:    Encodes horizontal mode
                    324: /*
                    325: /* DESCRIPTION: When horizontal mode is detected no further compaction can
                    326: /* can take place, so the next two run lengths are written to the output.
                    327: /* a0 is moved to after these runs.
                    328: */
                    329: 
                    330: horizontal_mode (code_lineptr,t4_lineptr,colour)
                    331: 
                    332: bit_string * t4_lineptr;
                    333: bit_string * code_lineptr;
                    334: char    colour;
                    335: 
                    336: {
                    337: int a2;
                    338: static code_word h_code = {3,0x0400};
                    339: full_code code;
                    340: 
                    341:    if (a0 == 0)    /* special case at start of line */
                    342:       a0 = 1;
                    343: 
                    344:    /* find a2 */
                    345:    a2 = *(++code_lineptr->run_pos);
                    346:       if (a2 >= STOP)
                    347:         code_lineptr->run_pos--;
                    348: 
                    349:    put_code (t4_lineptr,h_code);       /* code for horiz mode */
                    350: 
                    351:    /* get & put first run */
                    352:    code = get_code (a1-a0,colour);
                    353:    if (code.make.length != 0)
                    354:       put_code (t4_lineptr,code.make);
                    355:    put_code (t4_lineptr,code.term);
                    356: 
                    357:    /* get & put second run */
                    358:    code = get_code (a2-a1,1-colour);
                    359:    if (code.make.length != 0)
                    360:       put_code (t4_lineptr,code.make);
                    361:    put_code (t4_lineptr,code.term);
                    362: 
                    363:    a0=a2;
                    364: }
                    365: 
                    366: 
                    367: /* ROUTINE:     Put_code ()                                             */
                    368: /*                                                                      */
                    369: /* SYNOPSIS:    appends the code word to the 'line'.                    */
                    370: /*                                                                      */
                    371: 
                    372: put_code (lineptr,code)
                    373: 
                    374: bit_string *    lineptr;
                    375: code_word       code;
                    376: {
                    377: 
                    378: int             i;
                    379: short           mask;
                    380: 
                    381:    mask = MSB_MASK;     /* set mask to first bit of pattern */
                    382: 
                    383:    for (i=0; i< code.length ; i++) {
                    384:       if ((code.pattern  & mask) == WHITE)
                    385:         clr_bit (lineptr);
                    386:       else
                    387:         set_bit (lineptr);
                    388: 
                    389:       mask >>=  1;
                    390:    }
                    391: }
                    392: 
                    393: 
                    394: 
                    395: 
                    396: /* ROUTINE:     put_eoln                                                */
                    397: /*                                                                      */
                    398: /* SYNOPSIS:    Puts an end of line marker at the end of a t4 line.     */
                    399: /*              An end of line (eoln) marker is 11 (or more) zero's     */
                    400: /*              followed by a 1.                                        */
                    401: 
                    402: put_eoln (lineptr)
                    403: 
                    404: bit_string    * lineptr;
                    405: 
                    406: {
                    407: int i;
                    408: 
                    409:    for (i=0 ; i< 11; i++)
                    410:        clr_bit (lineptr);
                    411: 
                    412:    set_bit (lineptr);
                    413: 
                    414: }
                    415: 
                    416: 
                    417: 
                    418: /* ROUTINE:     get_runs
                    419:  *
                    420:  * SYNOPSIS:    set the runs change buffer fo the next input line
                    421:  *
                    422:  * DESCRIPTION: To optimise the input process, sequences of all 1's or 0's
                    423:  * - the most likely combinations are looked for as special cases, if not
                    424:  * found the runs are counted as bits.
                    425:  *
                    426:  */
                    427: 
                    428: get_runs (lineptr)
                    429: bit_string * lineptr;
                    430: 
                    431: {
                    432: register i,j;
                    433: char     colour = WHITE;
                    434: 
                    435:    *lineptr->run_pos++ = 0;
                    436: 
                    437:    for (i=1; i <= PIC_LINESIZE; i++)
                    438:        if (get_bit (lineptr) != colour) {
                    439:                *(lineptr->run_pos++) = i;
                    440:                colour = 1 - colour;
                    441:                }
                    442: 
                    443:    *lineptr->run_pos++ = STOP;
                    444:    *lineptr->run_pos = STOP;
                    445:  
                    446: }
                    447: 
                    448: /* ROUTINE:     set_output;
                    449:  *
                    450:  * SYNOPSIS:    Initialises the output buffers, writes the ENODE id, and
                    451:  * leaves room for the length (to be filled in later);
                    452: */
                    453: 
                    454: set_output (lineptr)
                    455: bit_string * lineptr;
                    456: {
                    457:    lineptr->dbuf_top += 5; /* leave room for length and id char*/
                    458:    lineptr->dbuf = lineptr->dbuf_top;
                    459:      
                    460:    lineptr->mask = BIT_MASK;
                    461: }
                    462: 
                    463: 
                    464: 
                    465: /* ROUTINE:     flush_output;
                    466: /*
                    467: /* SYNOPSIS:    flush the output buffer, and set file length;
                    468: */
                    469: 
                    470: flush_output (lineptr)
                    471: bit_string * lineptr;
                    472: {
                    473: long length, len;
                    474: int  count = 0,i;
                    475: 
                    476:    if ( lineptr->mask != BIT_MASK )     /* writes last char if necessary */
                    477:       lineptr->dbuf++;
                    478: 
                    479:    /* find and write length */
                    480:    len = length = lineptr->dbuf - lineptr->dbuf_top;
                    481:    
                    482:    if (length <= 127)  {       /* short form length */
                    483:         *(--lineptr->dbuf_top) = length; 
                    484:        *(--lineptr->dbuf_top) = 0x03;  /* bit map id */
                    485:        optlen = length + 2;
                    486:        }
                    487:    else {
                    488:        /* see how many bytes needed for length */
                    489:        while (len != 0) 
                    490:                {
                    491:                len >>= 8; 
                    492:                count++;
                    493:                }
                    494:        
                    495:        /* go back and write this info */
                    496:        
                    497:     
                    498:        for (i=0;i<count;i++) 
                    499:                *(--lineptr->dbuf_top) = (length >> (8 * i));
                    500:                
                    501:        *(--lineptr->dbuf_top) = 0x80 + count;  /* length marker*/
                    502:        *(--lineptr->dbuf_top) = 0x03;          /* bit map id */
                    503:                
                    504:        optlen = length + count + 1;
                    505:        }
                    506: }
                    507: 
                    508: 
                    509: /* ROUTINE:     set_input;
                    510: /*
                    511: /* SYNOPSIS:    Initialises the input buffers
                    512: */
                    513: 
                    514: set_input (lineptr)
                    515: bit_string * lineptr;
                    516: {
                    517:    lineptr->mask = BIT_MASK;
                    518:    lineptr->dbuf = lineptr->dbuf_top;
                    519:    lineptr->pos = *lineptr->dbuf++;
                    520: }

unix.superglobalmegacorp.com

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