Annotation of 43BSDReno/contrib/isode-beta/others/quipu/photo/encode.c, revision 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.