Annotation of researchv10no/cmd/bcp/CCITT.c, revision 1.1

1.1     ! root        1: /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved.              */
        !             2: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T.                */
        !             3: /* The copyright notice does not imply actual or intended publication. */
        !             4: /* AUTHORS:                                            */
        !             5: /*     H. S. Baird - ATT-BL MH - first versions        */
        !             6: 
        !             7: /* CCITT.c - functions for CCITT compression/decompression of binary images.
        !             8:    The following discussion is a summary of CCITT Recommendations T.4 and T.6
        !             9: on facsimile coding schemes and coding control functions for Group 3 and Group
        !            10: 4 facsimile apparatus (drafted at Malaga-Torremolinos, 1984).  They describe
        !            11: algorithms for invertible (lossless) compression and decompression of bilevel
        !            12: (black-and-white, not grey) 2D rectangular images of arbitrary height and
        !            13: width.  By convention the images are processed top-down, one horizontal scan
        !            14: line at a time.  It is not strictly necessary to know the height of an image
        !            15: before starting compression or decompression.  Width, however, must be known
        !            16: in advance in some cases (discussed below), and must remain constant for the
        !            17: whole image in all cases.  There are three distinct but intimately related
        !            18: standards:  Group 3 1-dimensional, Group 3 2-dimensional, and Group 4.
        !            19: VLSI hardware implementations always include all three.  The Group 3 encodings
        !            20: are used in the vast installed base of FAX machines.  Group 4 is not used
        !            21: in today's FAX machines, but seems to be the default standard in document image
        !            22: archiving applications.
        !            23:        The CCITT Group 3 FAX standard permits either 1-D or 2-D encoding.
        !            24: It is not easy to tell from an encoding which was used.  Both 1-D and 2-D
        !            25: assume fixed scanline length (in pixels), which must be known at encoding time.
        !            26:        Group 3 1-D (g31) code uses fixed ``modified Huffman'' codes for
        !            27: run-lengths, with two different code tables for black and white runs.  Each
        !            28: line is assumed to begin with a (possibly 0-length) white run.  Of course,
        !            29: the colors strictly alternate.  An empty (all-white) line is supposed to be
        !            30: spelled out with a full pixel count, although some decoders won't complain
        !            31: if just a 0-length count is used.  There are provisions for fill bits at the
        !            32: end of lines to allow slow receiving equipment to keep up.  Each line ends with
        !            33: an EOL code on which it may be possible to synchronize after transmission error.
        !            34:        Group 3 2-D (g32) encoding tries to exploit the slowly-changing nature
        !            35: of artwork from line to line.  It is a mixture of 1-D-coded lines and
        !            36: ``2-D''-coded lines describing small local changes relative to the immediately
        !            37: prior ``reference'' line.  1-D coding recurs every few (`k') lines, so that
        !            38: resynchronization is frequently possible.  K is usually 2 or 4, but the
        !            39: standard permits any number, even infinity, since the coding method used on
        !            40: a line is specified by which of two special EOLx codes is used to end the
        !            41: prior line.
        !            42:        CCITT Group 4 (g4) is like Group 3 2-D, but optimized to take advantage
        !            43: of a lossless communications channel or reliable storage medium (such as computer
        !            44: memory), where resynchronization is unnecessary.  Thus the first line is 2-D
        !            45: encoded referenced to an imaginary initial blank line, k is always infinity,
        !            46: and EOL's are not used at all.  It essential that the line-length be known in
        !            47: advance of both encoding and decoding, so that line-breaks can be triggered when
        !            48: that length is exceeded.  End of FAX buffer (end of page) is signaled by a
        !            49: special EOFB code.
        !            50:    On images of printed text and sparse line-graphics, g4-compressed files
        !            51: are often 15-40X smaller than bitmap (packed bits), 5X than bitfile(9.5),
        !            52: 2X than g31, and 2X than rle | pack.
        !            53: PERFORMANCE
        !            54:    On 10 printed A4 pages (business letters, technical reports, etc),
        !            55: at a resolution of 400 dpi:
        !            56:        binary:         2020 Kbytes     CPU secs (to compress binary)
        !            57:         pack:           200 - 380      17
        !            58:        bitfile(9.5):    150 - 360       ?
        !            59:        rle:             100 - 230       7.5
        !            60:         compress:        90 - 155      14
        !            61:        g31:              85 - 190      13
        !            62:        g32:              55 - 110      13
        !            63:        g4:               30 -  70      13
        !            64:    G4-compressed files are 15-40X smaller than binary, 5X than bitfile(9.5),
        !            65: 3.5X than rle, 2X than g31, and 2X than rle | pack.
        !            66: */
        !            67: 
        !            68: #include <stdio.h>
        !            69: #include <string.h>
        !            70: #include <ctype.h>
        !            71: #include "CPU.h"
        !            72: #include "stdocr.h"
        !            73: #include "rle.h"
        !            74: #include "bitio.h"
        !            75: #include "CCITT.h"
        !            76: 
        !            77: #define DEBUG 0                /* 0 disables compilation of all debugging code;
        !            78:                           1 compiles, but must enable particular parts below */
        !            79: #define NEW_TRAIL 1    /* enable new trailing-0 counts (has passed early tests) */
        !            80: #define dbg_trail 0
        !            81: 
        !            82: DST_table *ccitt_table()
        !            83: {   DST_context cx;
        !            84:        if((cx.t = (DST_table *)malloc(sizeof(DST_table)))==NULL)
        !            85:                abort("CCITT.c: build_tbl: can't alloc cx.t");
        !            86:        /* All tables have e[DST_white], e[DST_black], & e[DST_2d] entries */
        !            87:        cx.t->mny=3;
        !            88:        if((cx.t->e=(DST_entry *)malloc(cx.t->mny*sizeof(DST_entry)))==NULL)
        !            89:                abort("CCITT.c: build_tbl: can't alloc cx.t->e[%d]",cx.t->mny);
        !            90: 
        !            91:        cx.s = cx.c = DST_white;
        !            92:        cx.l = 0;
        !            93:        cx.t->e[cx.s].p[0] = '\0';
        !            94:        cx.t->e[cx.s].l = 0;
        !            95:        cx.t->e[cx.s].z = 0;
        !            96:        build_transits(cx);
        !            97: 
        !            98:        cx.s = cx.c = DST_black;
        !            99:        cx.l = 0;
        !           100:        cx.t->e[cx.s].p[0] = '\0';
        !           101:        cx.t->e[cx.s].l = 0;
        !           102:        cx.t->e[cx.s].z = 0;
        !           103:        build_transits(cx);
        !           104: 
        !           105:        cx.s = cx.c = DST_2d;
        !           106:        cx.l = 0;
        !           107:        cx.t->e[cx.s].p[0] = '\0';
        !           108:        cx.t->e[cx.s].l = 0;
        !           109:        cx.t->e[cx.s].z = 0;
        !           110:        build_transits(cx);
        !           111: 
        !           112: #if DEBUG
        !           113:        if(F) ccitt_err_tbl(cx.t);
        !           114: #endif
        !           115:        return(cx.t);
        !           116:        }
        !           117: 
        !           118: DST_state new_state(t)
        !           119:    DST_table *t;
        !           120: {      t->mny++;
        !           121:        if((t->e=(DST_entry *)realloc(t->e,t->mny*sizeof(DST_entry)))==NULL)
        !           122:                abort("can't realloc t->[%d]",t->mny);
        !           123:        return(t->mny-1);
        !           124:        }
        !           125: 
        !           126: /* The entry described by `cx' exists in the table, and its prefix `p' is
        !           127:    setup; create its transitions, and their next entries, recursively.  */
        !           128: build_transits(cx)
        !           129:     DST_context cx;
        !           130: #define entry cx.t->e[cx.s]
        !           131: #define transit entry.t[col]
        !           132: {   DST_color col;
        !           133:     DST_entry ne;      /* next entry */
        !           134:     DST_context ncx;   /* next Context */
        !           135:     char **s,**ss;     /* for searching code */
        !           136:     short *c,*cs;
        !           137:     int si,matching,longer;
        !           138:     char svch,col_str[2];
        !           139:        switch(cx.c) {
        !           140:            case DST_white:
        !           141:                ss=codewht;
        !           142:                cs=bitcwht;
        !           143:                break;
        !           144:            case DST_black:
        !           145:                ss=codeblk;
        !           146:                cs=bitcblk;
        !           147:                break;
        !           148:            case DST_2d:
        !           149:                ss=code2d;
        !           150:                cs=bitc2d;
        !           151:                break;
        !           152:            };
        !           153:        for(col=0;col<=1;col++) {
        !           154:                sprintf(col_str,"%1d",col);
        !           155:                ncx = cx;  ncx.l++; 
        !           156:                /* build a transition */
        !           157:                strcpy(ne.p,entry.p); strcat(ne.p,col_str);
        !           158:                ne.l = ncx.l;
        !           159:                if(col==0) ne.z = entry.z+1; else ne.z = 0;
        !           160:                /* count those that match new prefix */
        !           161:                longer=matching=0;
        !           162:                for(s=ss,c=cs,si=0; (*s)!=NULL; s++,c++,si++) {
        !           163:                        if(*c==ncx.l) {
        !           164:                                if(strcmp(*s,ne.p)==0) {
        !           165:                                        matching++;
        !           166:                                        switch(cx.c) {
        !           167:                                            case DST_white:
        !           168:                                            case DST_black:
        !           169:                                                transit.a = itor(si);
        !           170:                                                break;
        !           171:                                            case DST_2d:
        !           172:                                                transit.a = si;
        !           173:                                                break;
        !           174:                                            };
        !           175:                                        };
        !           176:                                }
        !           177:                        else if(*c>ncx.l) {
        !           178:                                svch=(*s)[ncx.l]; (*s)[ncx.l] = '\0';
        !           179:                                if(strcmp(*s,ne.p)==0) {
        !           180:                                        longer++;
        !           181:                                        };
        !           182:                                (*s)[ncx.l]=svch;
        !           183:                                };
        !           184:                        };
        !           185:                /* analyze results */
        !           186:                if(matching==0&&longer>0) {
        !           187:                        /* no match yet; go deeper */
        !           188:                        transit.a = DST_action_NULL;
        !           189:                        ncx.s = transit.s = new_state(cx.t);
        !           190:                        strcpy(cx.t->e[ncx.s].p,ne.p);
        !           191:                        cx.t->e[ncx.s].l = ne.l;
        !           192:                        cx.t->e[ncx.s].z = ne.z;
        !           193:                        build_transits(ncx);
        !           194:                        }
        !           195:                else if(matching==1&&longer==0) {
        !           196:                        /* unique leaf: good */
        !           197:                        /* picked up action earlier */
        !           198:                        switch(cx.c) {
        !           199:                            case DST_white:
        !           200:                            case DST_black:
        !           201:                                if(transit.a<=63) /* termination code */
        !           202:                                        transit.s = flip_color(cx.c); 
        !           203:                                else /* makeup code */
        !           204:                                        transit.s = cx.c;
        !           205:                                break;
        !           206:                            case DST_2d:
        !           207:                                /* legal end of code */
        !           208:                                transit.s = DST_state_NULL;
        !           209:                                break;
        !           210:                            };
        !           211:                        }
        !           212:                else {  /* illegal transition */
        !           213:                        transit.a = DST_action_ERROR;
        !           214:                        transit.s = DST_state_NULL;
        !           215:                        };
        !           216:                };
        !           217:        }
        !           218: 
        !           219: ccitt_err_tbl(t)
        !           220:     DST_table *t;
        !           221: {   int d;
        !           222:        ccitt_err_state(DST_white,t);
        !           223:        ccitt_err_state(DST_black,t);
        !           224:        ccitt_err_state(DST_2d,t);
        !           225:        }
        !           226: 
        !           227: ccitt_err_state(s,t)
        !           228:     DST_state s;
        !           229:     DST_table *t;
        !           230: {      err("%03d %s %2d %2d%*s %d %03d,%-4d  %d %03d,%-4d",
        !           231:                        s,t->e[s].p,t->e[s].l,t->e[s].z,14-strlen(t->e[s].p)," ",
        !           232:                        0,t->e[s].t[0].s,t->e[s].t[0].a,
        !           233:                        1,t->e[s].t[1].s,t->e[s].t[1].a
        !           234:                        );
        !           235:        if(t->e[s].t[0].s>1) ccitt_err_state(t->e[s].t[0].s,t);
        !           236:        if(t->e[s].t[1].s>1) ccitt_err_state(t->e[s].t[1].s,t);
        !           237:        }
        !           238: 
        !           239: /* Translate a stream of bits in CCITT FAX Group 3 (1-D) compression format
        !           240:    into a sequence of RLE_Lines.  Returns one (RLE_Line *) on each call (or NULL
        !           241:    if EOF or error).  The first pixel (black or white) in each g31 line is
        !           242:    assigned run index 0. */
        !           243: RLE_Line *g31_to_rlel(t,f,bof)
        !           244:     DST_table *t;
        !           245:     BITFILE *f;
        !           246:     boolean bof;       /* beginning of file */
        !           247: #define dbg_g31r_r (0) /* trace each run/EOL/ERR_SYN */
        !           248: #define dbg_g31r_c (0) /* trace each Huffman code (or, fill+EOL)*/
        !           249: #define dbg_g31r_t (0) /* trace each state-transition */
        !           250: {   static DST_context cx;
        !           251:     static RLE_Line rl;
        !           252:     static RLE_Run *r; /* prior, current runs */
        !           253:     int run,biti,sync,si,bitv;
        !           254:     boolean fill;
        !           255: /* color of 1st run in each line */
        !           256: #define g31_first_color DST_white
        !           257: /* reverse Black/White in output image */
        !           258: #define g31_negative 0
        !           259:        if(bof){if(T) { /* sync by skipping initial FILL & EOL code */
        !           260:                        sync=0;  while((bitv=getb(f))==0) sync++;
        !           261:                        if(bitv!=1||sync<11) {
        !           262: #if DEBUG
        !           263:                                if(dbg_g31r_c) {
        !           264:                                        fprintf(stderr,"BOF_ERR ");
        !           265:                                        for(si=0;si<sync;si++) fprintf(stderr,"0");
        !           266:                                        if(bitv==1) fprintf(stderr,"1\n");
        !           267:                                        else fprintf(stderr,"?\n");
        !           268:                                        };
        !           269: #endif
        !           270:                                return(NULL);
        !           271:                                }
        !           272: #if DEBUG
        !           273:                        else if(dbg_g31r_c){
        !           274:                                fprintf(stderr,"BOF_EOL ");
        !           275:                                for(si=0;si<sync;si++) fprintf(stderr,"0");
        !           276:                                fprintf(stderr,"1\n");
        !           277:                                };
        !           278: #endif
        !           279:                        };
        !           280:                /* start file expecting a run-code of a fixed color */
        !           281:                cx.s = cx.c = g31_first_color;
        !           282:                rl.y = -1;      /* assume first line is y==0 */
        !           283:                };
        !           284:        rl.y++;  rl.runs=0;  r = rl.r;  biti=run=0;
        !           285:        while(T) switch(getb(f)) {
        !           286:            case 0 :  /* next bit is 0 */
        !           287:                switch(t->e[cx.s].t[0].a) {
        !           288:                    case DST_action_ERROR:
        !           289:                        /* bad code: try to resynchronize */
        !           290: #if DEBUG
        !           291:                        if(dbg_g31r_t){
        !           292:                                fprintf(stderr,"%s %04d  %s0?...\n",
        !           293:                                        (cx.c==DST_white)? "W": "B",
        !           294:                                        t->e[cx.s].t[0].s,
        !           295:                                        t->e[cx.s].p);
        !           296:                                };
        !           297: #endif
        !           298:                        /* count trailing 0's so far (should be in table) */
        !           299: #if !NEW_TRAIL
        !           300:                        sync=1;
        !           301:                        si=strlen(t->e[cx.s].p)-1;
        !           302:                        while(si>=0&&t->e[cx.s].p[si]=='0') {sync++; si--;};
        !           303:                        fill = (si<0);  /* all 0's:  may be fill bits */
        !           304: #else
        !           305:                        sync=t->e[cx.s].z+1;
        !           306:                        fill = (sync>t->e[cx.s].l); /* all 0's:  maybe fill bits */
        !           307: #endif
        !           308: #if DEBUG
        !           309:                        if(dbg_trail) err("sync %d fill %d",sync,fill);
        !           310:                        if(dbg_g31r_c)fprintf(stderr,"ERR_SYN %s0?",t->e[cx.s].p);
        !           311: #endif
        !           312:                        while(sync<11) {
        !           313:                                switch(bitv=getb(f)) {
        !           314:                                        case 0:  sync++;
        !           315: #if DEBUG
        !           316:                                                if(dbg_g31r_c) fprintf(stderr,"0");
        !           317: #endif
        !           318:                                                break;
        !           319:                                        case 1:  sync=0;  fill=F;
        !           320: #if DEBUG
        !           321:                                                if(dbg_g31r_c) fprintf(stderr,"1");
        !           322: #endif
        !           323:                                                break;
        !           324:                                        case EOF:
        !           325: #if DEBUG
        !           326:                                                if(dbg_g31r_c) fprintf(stderr,"<EOF>\n");
        !           327: #endif
        !           328:                                                return(NULL);  break;
        !           329:                                        };
        !           330:                                };
        !           331:                        /* next `1' will synchronize */
        !           332:                        do {    switch(bitv=getb(f)) {
        !           333:                                        case 0:
        !           334: #if DEBUG
        !           335:                                                if(dbg_g31r_c) fprintf(stderr,"0");
        !           336: #endif
        !           337:                                                break;
        !           338:                                        case 1:
        !           339: #if DEBUG
        !           340:                                                if(dbg_g31r_c) fprintf(stderr,"1");
        !           341: #endif
        !           342:                                                break;
        !           343:                                        case EOF:
        !           344: #if DEBUG
        !           345:                                                if(dbg_g31r_c) fprintf(stderr,"<EOF>\n");
        !           346: #endif
        !           347:                                                return(NULL);  break;
        !           348:                                        };
        !           349:                                }
        !           350:                        while(bitv!=1);
        !           351: #if DEBUG
        !           352:                        if(dbg_g31r_c) fprintf(stderr,"\n");
        !           353:                        if(dbg_g31r_r) {
        !           354:                                if(fill) fprintf(stderr,"FILL_EOL\n");
        !           355:                                else fprintf(stderr,"ERR_SYN_EOL\n");
        !           356:                                };
        !           357: #endif
        !           358:                        /* start next line expecting a run-code of a fixed color */
        !           359:                        cx.s = cx.c = g31_first_color;
        !           360:                        return(&rl);
        !           361:                        break;
        !           362:                    case DST_action_NULL:
        !           363: #if DEBUG
        !           364:                        if(dbg_g31r_t)fprintf(stderr,"%s %04d  %s0\n",
        !           365:                                (cx.c==DST_white)? "W": "B",
        !           366:                                t->e[cx.s].t[0].s,
        !           367:                                t->e[cx.s].p);
        !           368: #endif
        !           369:                        cx.s = t->e[cx.s].t[0].s;
        !           370:                        break;
        !           371:                    case DST_EOL:
        !           372: #if DEBUG
        !           373:                        if(dbg_g31r_c)fprintf(stderr,"EOL     %s0\n",
        !           374:                                t->e[cx.s].p);
        !           375:                        if(dbg_g31r_r)fprintf(stderr,"EOL\n");
        !           376: #endif
        !           377:                        /* start next line expecting a run-code of a fixed color */
        !           378:                        cx.s = cx.c = g31_first_color;
        !           379:                        return(&rl);
        !           380:                        break;
        !           381:                    default:
        !           382: #if DEBUG
        !           383:                        if(dbg_g31r_c)fprintf(stderr,"%s%6d %s0\n",
        !           384:                                (cx.c==DST_white)? "W": "B",
        !           385:                                t->e[cx.s].t[0].a,
        !           386:                                t->e[cx.s].p);
        !           387: #endif
        !           388:                        if(t->e[cx.s].t[0].a<=63) {
        !           389:                                run += t->e[cx.s].t[0].a;
        !           390: #if DEBUG
        !           391:                                if(dbg_g31r_r)fprintf(stderr,"%s%6d\n",
        !           392:                                        (cx.c==DST_white)? "W": "B",
        !           393:                                        run);
        !           394: #endif
        !           395:                                biti += run;
        !           396:                                if(cx.c==DST_black^g31_negative) {
        !           397:                                        /* end of black run */
        !           398:                                        r->xe = biti-1;
        !           399:                                        r++; rl.runs++;
        !           400:                                        }
        !           401:                                else {  /* end of white run */
        !           402:                                        r->xs = biti;
        !           403:                                        };
        !           404:                                cx.c = flip_color(cx.c);
        !           405:                                run = 0;
        !           406:                                }
        !           407:                        else run += t->e[cx.s].t[0].a;
        !           408:                        cx.s = t->e[cx.s].t[0].s;
        !           409:                        break;
        !           410:                    };
        !           411:                break;
        !           412:            case 1:  /* next bit is 1 */
        !           413:                switch(t->e[cx.s].t[1].a) {
        !           414:                    case DST_action_ERROR:
        !           415:                        /* bad code: try to resynchronize */
        !           416: #if DEBUG
        !           417:                        if(dbg_g31r_t){
        !           418:                                fprintf(stderr,"%s %04d  %s1?...\n",
        !           419:                                        (cx.c==DST_white)? "W": "B",
        !           420:                                        t->e[cx.s].t[1].s,
        !           421:                                        t->e[cx.s].p);
        !           422:                                };
        !           423:                        if(dbg_g31r_c)fprintf(stderr,"ERR_SYN %s1?",t->e[cx.s].p);
        !           424: #endif
        !           425:                        /* no trailing 0's; can't be fill bits */
        !           426:                        sync=0;
        !           427:                        while(sync<11) {
        !           428:                                switch(bitv=getb(f)) {
        !           429:                                        case 0:  sync++;
        !           430: #if DEBUG
        !           431:                                                if(dbg_g31r_c) fprintf(stderr,"0");
        !           432: #endif
        !           433:                                                break;
        !           434:                                        case 1:  sync=0;
        !           435: #if DEBUG
        !           436:                                                if(dbg_g31r_c) fprintf(stderr,"1");
        !           437: #endif
        !           438:                                                break;
        !           439:                                        case EOF:
        !           440: #if DEBUG
        !           441:                                                if(dbg_g31r_c)
        !           442:                                                        fprintf(stderr,"<EOF>\n");
        !           443: #endif
        !           444:                                                return(NULL);  break;
        !           445:                                        };
        !           446:                                };
        !           447:                        /* next `1' will synchronize */
        !           448:                        do {    switch(bitv=getb(f)) {
        !           449:                                        case 0:
        !           450: #if DEBUG
        !           451:                                                if(dbg_g31r_c) fprintf(stderr,"0");
        !           452: #endif
        !           453:                                                break;
        !           454:                                        case 1:
        !           455: #if DEBUG
        !           456:                                                if(dbg_g31r_c) fprintf(stderr,"1");
        !           457: #endif
        !           458:                                                break;
        !           459:                                        case EOF:
        !           460: #if DEBUG
        !           461:                                                if(dbg_g31r_c)
        !           462:                                                        fprintf(stderr,"<EOF>\n");
        !           463: #endif
        !           464:                                                return(NULL);  break;
        !           465:                                        };
        !           466:                                }
        !           467:                        while(bitv!=1);
        !           468: #if DEBUG
        !           469:                        if(dbg_g31r_c) fprintf(stderr,"\n");
        !           470:                        if(dbg_g31r_r) fprintf(stderr,"ERR_SYN_EOL\n");
        !           471: #endif
        !           472:                        /* start next line expecting a run-code of a fixed color */
        !           473:                        cx.s = cx.c = g31_first_color;
        !           474:                        return(&rl);
        !           475:                        break;
        !           476:                    case DST_action_NULL:
        !           477: #if DEBUG
        !           478:                        if(dbg_g31r_t)fprintf(stderr,"%s %04d  %s1\n",
        !           479:                                (cx.c==DST_white)? "W": "B",
        !           480:                                t->e[cx.s].t[1].s,
        !           481:                                t->e[cx.s].p);
        !           482: #endif
        !           483:                        cx.s = t->e[cx.s].t[1].s;
        !           484:                        break;
        !           485:                    case DST_EOL:
        !           486: #if DEBUG
        !           487:                        if(dbg_g31r_c)fprintf(stderr,"EOL     %s1\n",
        !           488:                                t->e[cx.s].p);
        !           489:                        if(dbg_g31r_r)fprintf(stderr,"EOL\n");
        !           490: #endif
        !           491:                        /* start next line expecting a run-code of a fixed color */
        !           492:                        cx.s = cx.c = g31_first_color;
        !           493:                        return(&rl);
        !           494:                        break;
        !           495:                    default:
        !           496: #if DEBUG
        !           497:                        if(dbg_g31r_c)fprintf(stderr,"%s%6d %s1\n",
        !           498:                                (cx.c==DST_white)? "W": "B",
        !           499:                                t->e[cx.s].t[1].a,
        !           500:                                t->e[cx.s].p);
        !           501: #endif
        !           502:                        if(t->e[cx.s].t[1].a<=63) {
        !           503:                                run += t->e[cx.s].t[1].a;
        !           504: #if DEBUG
        !           505:                                if(dbg_g31r_r)fprintf(stderr,"%s%6d\n",
        !           506:                                        (cx.c==DST_white)? "W": "B",
        !           507:                                        run);
        !           508: #endif
        !           509:                                biti += run;
        !           510:                                if(cx.c==DST_black^g31_negative) {
        !           511:                                        /* end of black run */
        !           512:                                        r->xe = biti-1;
        !           513:                                        r++; rl.runs++;
        !           514:                                        }
        !           515:                                else {  /* end of white run */
        !           516:                                        r->xs = biti;
        !           517:                                        };
        !           518:                                cx.c = flip_color(cx.c);
        !           519:                                run = 0;
        !           520:                                }
        !           521:                        else run += t->e[cx.s].t[1].a;
        !           522:                        cx.s = t->e[cx.s].t[1].s;
        !           523:                        break;
        !           524:                    };
        !           525:                break;
        !           526:            case EOF:
        !           527:                return(NULL);
        !           528:                break;
        !           529:            default:
        !           530:                return(NULL);
        !           531:                break;
        !           532:            };
        !           533:        /* never come here:  return() variously from cases above */
        !           534:        }
        !           535: 
        !           536: /* Translate a sequence of RLE_Line's (describing a binary image)
        !           537:    into a file (a stream of bits) in CCITT FAX Group 3 (1-D) compression format.
        !           538:    BOF_to_g31() must be called first; then call rlel_to_g31() for each line
        !           539:    (including blank lines); finally, EOF_to_g31() must be called.  Each line's
        !           540:    EOL and the RTC's first EOL are padded so they end on a byte boundary.
        !           541:    */
        !           542: /* debugging flags:  trace to stderr */
        !           543: #define dbg_rg31_e (0) /* entry */
        !           544: #define dbg_rg31_r (0) /* runs */
        !           545: #define dbg_rg31_s (0) /* bitstrings */
        !           546: 
        !           547: #if DEBUG
        !           548: #define bits_g31(bits) { \
        !           549:        cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;};  \
        !           550:        if(dbg_rg31_s) fprintf(stderr,"%s",(bits)); \
        !           551:        if(dbg_rg31_r) fprintf(stderr," "); \
        !           552:        }
        !           553: #define EOL_g31 { \
        !           554:        if(dbg_rg31_r) fprintf(stderr,"EOL     "); \
        !           555:        bits_g31(EOLSTRING); \
        !           556:        if(dbg_rg31_r) fprintf(stderr,"\n"); \
        !           557:        }
        !           558: #else
        !           559: #define bits_g31(bits) { \
        !           560:        cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;};  \
        !           561:        }
        !           562: #define EOL_g31 { \
        !           563:        bits_g31(EOLSTRING); \
        !           564:        }
        !           565: #endif
        !           566: 
        !           567: BOF_to_g31(f)
        !           568:     BITFILE *f;        /* state of output bitfile */
        !           569: {   char *cs;
        !           570:        EOL_g31;
        !           571:        }
        !           572: 
        !           573: rlel_to_g31(rl,wid,f)
        !           574:     RLE_Line *rl;      /* line of runs:  if NULL, then blank */
        !           575:     int wid;           /* width of an output line in pixels */
        !           576:     BITFILE *f;                /* state of output bitfile */
        !           577: {   int pi;            /* input pixel index on line */
        !           578:     RLE_Run *rp,*pp,*sp;
        !           579:     int runl,codi;
        !           580:     char *cs,*p01;
        !           581: #if DEBUG
        !           582: #define Wrun_g31(rn) { \
        !           583:        runl=(rn); \
        !           584:        if(dbg_rg31_r) fprintf(stderr,"W %5d ",runl); \
        !           585:        while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g31(p01); runl-=2560;}; \
        !           586:        p01=codewht[codi=rtoi(runl)]; bits_g31(p01); \
        !           587:        if(codi>=64) {p01=codewht[runl%64]; bits_g31(p01);}; \
        !           588:        if(dbg_rg31_r) fprintf(stderr,"\n"); \
        !           589:        }
        !           590: #else
        !           591: #define Wrun_g31(rn) { \
        !           592:        runl=(rn); \
        !           593:        while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g31(p01); runl-=2560;}; \
        !           594:        p01=codewht[codi=rtoi(runl)]; bits_g31(p01); \
        !           595:        if(codi>=64) {p01=codewht[runl%64]; bits_g31(p01);}; \
        !           596:        }
        !           597: #endif
        !           598: #if DEBUG
        !           599: #define Brun_g31(rn) { \
        !           600:        runl=(rn); \
        !           601:        if(dbg_rg31_r) fprintf(stderr,"B %5d ",runl); \
        !           602:        while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g31(p01); runl-=2560;}; \
        !           603:        p01=codeblk[codi=rtoi(runl)]; bits_g31(p01); \
        !           604:        if(codi>=64) {p01=codeblk[runl%64]; bits_g31(p01);}; \
        !           605:        if(dbg_rg31_r) fprintf(stderr,"\n"); \
        !           606:        }
        !           607: 
        !           608: #else
        !           609: #define Brun_g31(rn) { \
        !           610:        runl=(rn); \
        !           611:        while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g31(p01); runl-=2560;}; \
        !           612:        p01=codeblk[codi=rtoi(runl)]; bits_g31(p01); \
        !           613:        if(codi>=64) {p01=codeblk[runl%64]; bits_g31(p01);}; \
        !           614:        }
        !           615: #endif
        !           616: #if DEBUG
        !           617:        if(dbg_rg31_e) err("rlel_to_g31(rl[y%d,r%d])",rl->y,rl->runs);
        !           618: #endif
        !           619:        if(rl!=NULL&&rl->runs>0) {
        !           620:                pi=0;   /* bit to write next */
        !           621: #if DEBUG
        !           622:                if(dbg_rg31_e) err("rlel_to_g31(rl[y%d,r%d])",rl->y,rl->runs);
        !           623: #endif
        !           624:                for(sp=(rp=rl->r)+rl->runs; rp<sp; rp++) {
        !           625:                        Wrun_g31(rp->xs-pi);  pi=rp->xs;
        !           626:                        Brun_g31(rp->xe-pi+1);  pi=rp->xe+1;
        !           627:                        };
        !           628:                if((--rp)->xe+1<wid) Wrun_g31(wid-rp->xe-1);
        !           629:                }
        !           630:        else {  
        !           631: #if DEBUG
        !           632:                if(dbg_rg31_e) err("rlel_to_g31(rl[y?,r0])");
        !           633: #endif
        !           634:                Wrun_g31(wid);  /* blank (all-white) scanline */
        !           635:                };
        !           636:        /* fill so that EOL ends on byte boundary */
        !           637:        padb(f,0,8,EOLLENGTH);
        !           638: #if DEBUG
        !           639:        if(dbg_rg31_s) fprintf(stderr,"+0?");
        !           640: #endif
        !           641:        EOL_g31;
        !           642:        }
        !           643: 
        !           644: EOF_to_g31(f)
        !           645:     BITFILE *f;
        !           646: {   char *cs;
        !           647:        /* fill so that EOL ends on byte boundary */
        !           648:        padb(f,0,8,EOLLENGTH);
        !           649: #if DEBUG
        !           650:        if(dbg_rg31_s) fprintf(stderr,"+0?");
        !           651: #endif
        !           652:        /* write RTC */
        !           653:        EOL_g31;
        !           654:        EOL_g31;
        !           655:        EOL_g31;
        !           656:        EOL_g31;
        !           657:        EOL_g31;
        !           658:        EOL_g31;
        !           659:        }
        !           660: 
        !           661: /* Macro for use within g32_to_rlel, to read one 1-D Modified Huffman coded
        !           662:    run-length of a given color, placing the result in a given variable.
        !           663:    Exceptionally, goto trap_eol, trap_eof, or trap_code_err.
        !           664:   */
        !           665: #if DEBUG
        !           666: #define g32_1d_run(C,V) { \
        !           667:        run = 0; \
        !           668:        do {    cx.tr.s = (C); \
        !           669:                do {    px = cx; \
        !           670:                        switch(bitv=getb(f)) { \
        !           671:                            case 0 :  cx.tr=t->e[cx.tr.s].t[0];  break; \
        !           672:                            case 1 :  cx.tr=t->e[cx.tr.s].t[1];  break; \
        !           673:                            case EOF :  goto trap_eof;  break; \
        !           674:                            }; \
        !           675:                        } \
        !           676:                while(cx.tr.a==DST_action_NULL); \
        !           677:                switch(cx.tr.a) { \
        !           678:                    case DST_EOL : \
        !           679:                        if(dbg_g32r_c)fprintf(stderr,"EOL     %s\n",EOLSTRING); \
        !           680:                        goto trap_eol; \
        !           681:                        break; \
        !           682:                    case DST_action_ERROR :  goto trap_code_err;  break; \
        !           683:                    default : \
        !           684:                        if(dbg_g32r_c)fprintf(stderr,"%s%6d %s%d\n", \
        !           685:                                ((C)==DST_white)? "W": "B", \
        !           686:                                cx.tr.a, \
        !           687:                                t->e[px.tr.s].p, \
        !           688:                                bitv); \
        !           689:                        run += cx.tr.a; \
        !           690:                        break; \
        !           691:                    }; \
        !           692:                } \
        !           693:        while(cx.tr.a>63); \
        !           694:        (V) = run; \
        !           695:        }
        !           696: #else
        !           697: #define g32_1d_run(C,V) { \
        !           698:        run = 0; \
        !           699:        do {    cx.tr.s = (C); \
        !           700:                do {    px = cx; \
        !           701:                        switch(bitv=getb(f)) { \
        !           702:                            case 0 :  cx.tr=t->e[cx.tr.s].t[0];  break; \
        !           703:                            case 1 :  cx.tr=t->e[cx.tr.s].t[1];  break; \
        !           704:                            case EOF :  goto trap_eof;  break; \
        !           705:                            }; \
        !           706:                        } \
        !           707:                while(cx.tr.a==DST_action_NULL); \
        !           708:                switch(cx.tr.a) { \
        !           709:                    case DST_EOL : \
        !           710:                        goto trap_eol; \
        !           711:                        break; \
        !           712:                    case DST_action_ERROR :  goto trap_code_err;  break; \
        !           713:                    default : \
        !           714:                        run += cx.tr.a; \
        !           715:                        break; \
        !           716:                    }; \
        !           717:                } \
        !           718:        while(cx.tr.a>63); \
        !           719:        (V) = run; \
        !           720:        }
        !           721: #endif
        !           722: 
        !           723: /* Translate a stream of bits in CCITT FAX Group 3 (2-D) compression format
        !           724:    into a sequence of RLE_Lines.  Returns one (RLE_Line *) on each call (or NULL
        !           725:    if EOF or error).  The first pixel (black or white) in each g32 line is
        !           726:    assigned run index 0. */
        !           727: RLE_Line *g32_to_rlel(t,f,bof)
        !           728:     DST_table *t;
        !           729:     BITFILE *f;
        !           730:     boolean bof;       /* beginning of file */
        !           731: #define dbg_g32r_e (0) /* entry/exit */
        !           732: #define dbg_g32r_r (0) /* trace each run/EOL/ERR_SYN */
        !           733: #define dbg_g32r_c (0) /* trace each Huffman code (or, fill+EOL)*/
        !           734: #define dbg_g32r_t (0) /* trace each state-transition */
        !           735: #define g32r_strict (1)        /* 1 is CORRECT: explicitly code the last black pel */
        !           736: {   static RLE_Line rl0,rl1,*prl,*crl; /* prior, current run-lines */
        !           737:     RLE_Line *swrl;
        !           738:     int bitv;          /* the last-read bit value */
        !           739:     DST_context cx,px; /* the current/prior decoding context */
        !           740:     RLE_Run *cr,*pr,*pre;      /* into current/prior rle lines */      
        !           741:     RLE_Run *pra0;     /* rightmost in prior line with xe<=a0 (if none: prl->r) */
        !           742:     int run,sync,si,rtc_eols;
        !           743:     boolean fill;
        !           744:     /* pixel indices (0,1,...):  current-line a*; prior-line b*.
        !           745:        a0 is the index of the most recently completely encoded bit */
        !           746:     int a0,a1,a2,b1,b2;        
        !           747:     DST_color a0_color;  /* a0's color:  same as a2 & b2, opposite of a1 & b1 */
        !           748:     int a01,a12;        /* lengths of runs a0-a1 & a1-a2 */
        !           749: #define g32_first_color DST_white      /* color of 1st run in each line */
        !           750: #define g32_negative (0)       /* if 1, invert Black/White on output */
        !           751: #define swap_rl(f,b) {swrl=(f); (f)=(b); (b)=swrl;}
        !           752: /* detect b1 & b2:  sensitive to a0, a0_color, and prior runs *pr *(pr+1) */
        !           753: #define g32r_find_Bb1Wb2 { \
        !           754:        /* find 1st black changing pel>a0 */ \
        !           755:        /* advance pra0 as far as possible s.t. pra0->xe<=a0 */ \
        !           756:        while((pra0+1)<pre && (pra0+1)->xe<=a0) pra0++; \
        !           757:        /* look beyond pra0 */ \
        !           758:        pr=pra0;  while(pr<pre && (b1=pr->xs)<=a0) pr++; \
        !           759:        /* move b2 to 1st changing white pel > b1 */ \
        !           760:        if(pr<pre) b2=pr->xe+1; \
        !           761:        else b1=b2=prl->len; \
        !           762:        }
        !           763: #define g32r_find_Wb1Bb2 { \
        !           764:        /* find 1st white changing pel>a0 */ \
        !           765:        /* advance pra0 as far as possible s.t. pra0->xe<=a0 */ \
        !           766:        while((pra0+1)<pre && (pra0+1)->xe<=a0) pra0++; \
        !           767:        /* look beyond pra0 */ \
        !           768:        pr=pra0;  while(pr<pre && (b1=pr->xe+1)<=a0) pr++; \
        !           769:        /* move b2 to 1st changing black pel > b1 */ \
        !           770:        if(pr<pre) { \
        !           771:                if((pr+1)<pre) b2=(pr+1)->xs; \
        !           772:                else b2=prl->len; \
        !           773:                } \
        !           774:        else b1=b2=prl->len; \
        !           775:        }
        !           776: #define g32r_find_b1b2 {if(a0_color==DST_white) g32r_find_Bb1Wb2 else g32r_find_Wb1Bb2;}
        !           777: 
        !           778: #if DEBUG
        !           779: if(dbg_g32r_e) fprintf(stderr,"g32_to_rlel(t,bf,bof%d)\n",bof);
        !           780: #endif
        !           781: if(bof){crl= &rl0;  crl->y= -1;  crl->len=0;  crl->runs=0;
        !           782:        prl= &rl1;  prl->y= -1;  prl->len=0;  prl->runs=0;
        !           783:        /* sync by skipping initial FILL & EOL code */
        !           784:        sync=0;  while((bitv=getb(f))==0) sync++;
        !           785:        if(bitv!=1||sync<11) {
        !           786: #if DEBUG
        !           787:                if(dbg_g32r_c) {
        !           788:                        fprintf(stderr,"BOF_ERR ");
        !           789:                        for(si=0;si<sync;si++) fprintf(stderr,"0");
        !           790:                        if(bitv==1) fprintf(stderr,"1\n");
        !           791:                        else fprintf(stderr,"?\n");
        !           792:                        };
        !           793: #endif
        !           794:                return(NULL);
        !           795:                }
        !           796: #if DEBUG
        !           797:        else if(dbg_g32r_c){
        !           798:                fprintf(stderr,"BOF_EOL ");
        !           799:                for(si=0;si<sync;si++) fprintf(stderr,"0");
        !           800:                fprintf(stderr,"1\n");
        !           801:                };
        !           802: #else
        !           803:                ;
        !           804: #endif
        !           805:        prl->y = -1;  crl->y = 0;
        !           806:        }
        !           807: else crl->y = prl->y + 1;
        !           808: 
        !           809: pre = (pra0=pr=prl->r) + prl->runs;    /* prior line */
        !           810: crl->runs=0;  cr=crl->r-1;             /* current line */
        !           811: /* start on an imaginary white pixel just to left of margin */
        !           812: a0= -1;  a0_color = DST_white; 
        !           813: 
        !           814: /* check 1-D / 2-D bit immediately after prior EOL */
        !           815: switch(bitv=getb(f)) {
        !           816:     case 0 :  /* 2-dimensionally encoded line */
        !           817: #if DEBUG
        !           818:        if(dbg_g32r_c) fprintf(stderr,"2D_LINE 0\n");
        !           819: #endif
        !           820:        /* start b1/b2 on prior line's first black pixel, etc;
        !           821:           if none, then place off end of line */
        !           822:        if(pr<pre) {b1=pr->xs; b2=pr->xe+1;} else b1=b2=prl->len;
        !           823:        /* parse a sequence of 2D codes... */
        !           824:        while(T/* exited only via goto trap_* and return */) {
        !           825:                cx.tr.s = DST_2d;  cx.tr.a = DST_action_NULL;
        !           826: #if DEBUG
        !           827:                if(dbg_g32r_t)fprintf(stderr,"(%d,%d)\n",cx.tr.s,cx.tr.a);
        !           828: #endif
        !           829:                do {    switch(bitv=getb(f)) {
        !           830:                            case 0 :
        !           831:                            case 1 :
        !           832:                                cx.tr=t->e[cx.tr.s].t[bitv];
        !           833:                                break;
        !           834:                            case EOF:  goto trap_eof;  break;
        !           835:                            };
        !           836: #if DEBUG
        !           837:                        if(dbg_g32r_t)fprintf(stderr,"%d->(%d,%d)\n",
        !           838:                                        bitv,cx.tr.s,cx.tr.a);
        !           839: #endif
        !           840:                        }
        !           841:                while(cx.tr.a==DST_action_NULL);
        !           842: #if DEBUG
        !           843:                if(dbg_g32r_t)fprintf(stderr,"%s %04d  %s0\n",
        !           844:                        (cx.c==DST_white)? "W": "B",
        !           845:                        cx.tr.s,
        !           846:                        t->e[cx.tr.s].p);
        !           847: #endif
        !           848:                switch(cx.tr.a) {
        !           849:                    case i2D_V0:
        !           850: #if DEBUG
        !           851:                        if(dbg_g32r_c)
        !           852:                                fprintf(stderr,"V0      %s\n",code2d[cx.tr.a]);
        !           853: #endif
        !           854:                        a1=b1;
        !           855:                        /* encode a0 to a1-1 */
        !           856:                        if(a0_color==DST_black) cr->xe=a1-1;
        !           857:                        /* move a0 to a1 */
        !           858:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !           859:                        a0_color = flip_color(a0_color);
        !           860:                        /* encode a0 */
        !           861:                        if(a0_color==DST_black)
        !           862:                                { crl->runs++;  (++cr)->xs = a0;  cr->xe = a0; };
        !           863: #if g32r_strict
        !           864:                        if(a0==prl->len-1)
        !           865:                                { a0++;  goto trap_expecting_eol; };
        !           866: #endif
        !           867:                        g32r_find_b1b2;
        !           868:                        break;
        !           869:                    case i2D_VR1:
        !           870: #if DEBUG
        !           871:                        if(dbg_g32r_c)
        !           872:                                fprintf(stderr,"VR1     %s\n",code2d[cx.tr.a]);
        !           873: #endif
        !           874:                        a1=b1+1;
        !           875:                        /* encode a0 to a1-1 */
        !           876:                        if(a0_color==DST_black) cr->xe=a1-1;
        !           877:                        /* move a0 to a1 */
        !           878:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !           879:                        a0_color = flip_color(a0_color);
        !           880:                        /* encode a0 */
        !           881:                        if(a0_color==DST_black)
        !           882:                                { crl->runs++;  (++cr)->xs = a0;  cr->xe = a0; };
        !           883: #if !g32r_strict
        !           884:                        if(a0==prl->len-1)
        !           885:                                { a0++;  goto trap_expecting_eol; };
        !           886: #endif
        !           887:                        g32r_find_b1b2;
        !           888:                        break;
        !           889:                    case i2D_VR2:
        !           890: #if DEBUG
        !           891:                        if(dbg_g32r_c)
        !           892:                                fprintf(stderr,"VR2     %s\n",code2d[cx.tr.a]);
        !           893: #endif
        !           894:                        a1=b1+2;
        !           895:                        /* encode a0 to a1-1 */
        !           896:                        if(a0_color==DST_black) cr->xe=a1-1;
        !           897:                        /* move a0 to a1 */
        !           898:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !           899:                        a0_color = flip_color(a0_color);
        !           900:                        /* encode a0 */
        !           901:                        if(a0_color==DST_black)
        !           902:                                { crl->runs++;  (++cr)->xs = a0;  cr->xe = a0; };
        !           903: #if !g32r_strict
        !           904:                        if(a0==prl->len-1)
        !           905:                                { a0++;  goto trap_expecting_eol; };
        !           906: #endif
        !           907:                        g32r_find_b1b2;
        !           908:                        break;
        !           909:                    case i2D_VR3:
        !           910: #if DEBUG
        !           911:                        if(dbg_g32r_c)
        !           912:                                fprintf(stderr,"VR3     %s\n",code2d[cx.tr.a]);
        !           913: #endif
        !           914:                        a1=b1+3;
        !           915:                        /* encode a0 to a1-1 */
        !           916:                        if(a0_color==DST_black) cr->xe=a1-1;
        !           917:                        /* move a0 to a1 */
        !           918:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !           919:                        a0_color = flip_color(a0_color);
        !           920:                        /* encode a0 */
        !           921:                        if(a0_color==DST_black)
        !           922:                                { crl->runs++;  (++cr)->xs = a0;  cr->xe = a0; };
        !           923: #if !g32r_strict
        !           924:                        if(a0==prl->len-1)
        !           925:                                { a0++;  goto trap_expecting_eol; };
        !           926: #endif
        !           927:                        g32r_find_b1b2;
        !           928:                        break;
        !           929:                    case i2D_VL1:
        !           930: #if DEBUG
        !           931:                        if(dbg_g32r_c)
        !           932:                                fprintf(stderr,"VL1     %s\n",code2d[cx.tr.a]);
        !           933: #endif
        !           934:                        if((a1=b1-1)<0) err("g32_to_rlel: VL1 backs up to %d",a1);
        !           935:                        /* encode a0 to a1-1 */
        !           936:                        if(a0_color==DST_black) cr->xe=a1-1;
        !           937:                        /* move a0 to a1 */
        !           938:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !           939:                        a0_color = flip_color(a0_color);
        !           940:                        /* encode a0 */
        !           941:                        if(a0_color==DST_black)
        !           942:                                { crl->runs++;  (++cr)->xs = a0;  cr->xe = a0; };
        !           943: #if !g32_strict
        !           944:                        if(a0==prl->len-1)
        !           945:                                { a0++;  goto trap_expecting_eol; };
        !           946: #endif
        !           947:                        g32r_find_b1b2;
        !           948:                        break;
        !           949:                    case i2D_VL2:
        !           950: #if DEBUG
        !           951:                        if(dbg_g32r_c)
        !           952:                                fprintf(stderr,"VL2     %s\n",code2d[cx.tr.a]);
        !           953: #endif
        !           954:                        if((a1=b1-2)<0) err("g32_to_rlel: VL2 backs up to %d",a1);
        !           955:                        /* encode a0 to a1-1 */
        !           956:                        if(a0_color==DST_black) cr->xe=a1-1;
        !           957:                        /* move a0 to a1 */
        !           958:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !           959:                        a0_color = flip_color(a0_color);
        !           960:                        /* encode a0 */
        !           961:                        if(a0_color==DST_black)
        !           962:                                { crl->runs++;  (++cr)->xs = a0;  cr->xe = a0; };
        !           963: #if !g32r_strict
        !           964:                        if(a0==prl->len-1)
        !           965:                                { a0++;  goto trap_expecting_eol; };
        !           966: #endif
        !           967:                        g32r_find_b1b2;
        !           968:                        break;
        !           969:                    case i2D_VL3:
        !           970: #if DEBUG
        !           971:                        if(dbg_g32r_c)
        !           972:                                fprintf(stderr,"VL3     %s\n",code2d[cx.tr.a]);
        !           973: #endif
        !           974:                        if((a1=b1-3)<0) err("g32_to_rlel: VL3 backs up to %d",a1);
        !           975:                        /* encode a0 to a1-1 */
        !           976:                        if(a0_color==DST_black) cr->xe=a1-1;
        !           977:                        /* move a0 to a1 */
        !           978:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !           979:                        a0_color = flip_color(a0_color);
        !           980:                        /* encode a0 */
        !           981:                        if(a0_color==DST_black)
        !           982:                                { crl->runs++;  (++cr)->xs = a0;  cr->xe = a0; };
        !           983: #if !g32r_strict
        !           984:                        if(a0==prl->len-1)
        !           985:                                { a0++;  goto trap_expecting_eol; };
        !           986: #endif
        !           987:                        g32r_find_b1b2;
        !           988:                        break;
        !           989:                    case i2D_PASS:
        !           990: #if DEBUG
        !           991:                        if(dbg_g32r_c)
        !           992:                                fprintf(stderr,"PASS    %s\n",code2d[cx.tr.a]);
        !           993: #endif
        !           994:                        /* move a0 to b2; no change of color */
        !           995:                        a0=b2;  if(a0>=prl->len) goto trap_expecting_eol;
        !           996:                        if(a0_color==DST_black) cr->xe = a0;
        !           997: #if !g32r_strict
        !           998:                        if(a0==prl->len-1)
        !           999:                                { a0++;  goto trap_expecting_eol; };
        !          1000: #endif
        !          1001:                        g32r_find_b1b2;
        !          1002:                        break;
        !          1003:                    case i2D_HORIZ:
        !          1004: #if DEBUG
        !          1005:                        if(dbg_g32r_c)
        !          1006:                                fprintf(stderr,"HORIZ   %s\n",code2d[cx.tr.a]);
        !          1007: #endif
        !          1008:                        if(a0_color==DST_white) {
        !          1009:                                if(a0<0) a0=0;  /* first run in line starts at 0 */
        !          1010:                                g32_1d_run(DST_white,a01);  a1 = a0 + a01;
        !          1011:                                g32_1d_run(DST_black,a12);  a2 = a1 + a12;
        !          1012:                                if(a12>0) /* Black run of >0 length */ {
        !          1013:                                        crl->runs++;
        !          1014:                                        (++cr)->xs = a1;
        !          1015:                                        cr->xe = a2-1;
        !          1016:                                        };
        !          1017:                                a0 = a2;        /* still white */
        !          1018:                                if(a0>=prl->len) goto trap_expecting_eol;
        !          1019:                                /* encode a0 */
        !          1020: #if !g32r_strict
        !          1021:                                if(a0==prl->len-1)
        !          1022:                                        { a0++;  goto trap_expecting_eol; };
        !          1023: #endif
        !          1024:                                g32r_find_Bb1Wb2;
        !          1025:                                }
        !          1026:                        else {  g32_1d_run(DST_black,a01);  a1 = a0 + a01;
        !          1027:                                g32_1d_run(DST_white,a12);  a2 = a1 + a12;
        !          1028:                                if(a01>0) /* Black run of >0 length */ {
        !          1029:                                        cr->xe = a1 - 1;
        !          1030:                                        }
        !          1031:                                else {  /* 0-length: very peculiar: ignore */
        !          1032:                                        fprintf(stderr,
        !          1033:                                           "g32_to_rlel: HORIZ B%d! W%d - ignore\n",
        !          1034:                                           a01,a12);
        !          1035:                                        cr--; crl->runs--;
        !          1036:                                        };
        !          1037:                                a0 = a2;        /* still black */
        !          1038:                                if(a0>=prl->len) goto trap_expecting_eol;
        !          1039:                                /* encode a0 */
        !          1040:                                crl->runs++;  (++cr)->xs = a0;
        !          1041: #if !g32r_strict
        !          1042:                                if(a0==prl->len-1) {
        !          1043:                                        cr->xe = a0;
        !          1044:                                        a0++;
        !          1045:                                        goto trap_expecting_eol;
        !          1046:                                        };
        !          1047: #endif
        !          1048:                                g32r_find_Wb1Bb2;
        !          1049:                                };
        !          1050:                        break;
        !          1051:                    case i2D_EOL:
        !          1052: #if DEBUG
        !          1053:                        if(dbg_g32r_c)
        !          1054:                                fprintf(stderr,"EOL     %s\n",code2d[cx.tr.a]);
        !          1055: #endif
        !          1056:                        goto trap_eol;
        !          1057:                        break;
        !          1058:                    case DST_action_ERROR:  goto trap_code_err;  break;
        !          1059:                    };
        !          1060:                };
        !          1061:        break;
        !          1062:     case 1 :  /* 1-dimensionally encoded line */
        !          1063: #if DEBUG
        !          1064:        if(dbg_g32r_c) fprintf(stderr,"1D_LINE 1\n");
        !          1065: #endif
        !          1066:        /* read a sequence of 1-D runcodes... */
        !          1067:        while(T/* exit only via goto trap_X */) {
        !          1068:                g32_1d_run(a0_color,a01);
        !          1069:                a1 = ((a0>=0)? a0 : 0) + a01;
        !          1070:                if(a01>0) {
        !          1071:                        /* encode a0 through a1-1 */
        !          1072:                        if(a0_color==DST_black^g32_negative) {
        !          1073:                                /* output-black run */
        !          1074:                                crl->runs++;
        !          1075:                                (++cr)->xs=((a0>=0)? a0 : 0);
        !          1076:                                cr->xe=a1-1;
        !          1077:                                };
        !          1078:                        };
        !          1079:                a0=a1;
        !          1080:                a0_color=flip_color(a0_color);
        !          1081:                if(prl->len>0 && a0>=prl->len) goto trap_expecting_eol;
        !          1082:                };
        !          1083:        break;
        !          1084:     case EOF :  goto trap_eof;  break;
        !          1085:     };
        !          1086: 
        !          1087: /* come here via goto's: all these traps return() */
        !          1088: 
        !          1089: trap_expecting_eol:    /* come here expecting to see EOL or FILL+EOL */
        !          1090:        sync=0;  while((bitv=getb(f))==0) sync++;
        !          1091:        switch(bitv) {
        !          1092:            case 1:
        !          1093:                if(sync==11) {
        !          1094: #if DEBUG
        !          1095:                        if(dbg_g32r_c){
        !          1096:                                fprintf(stderr,"EOL     %s\n",EOLSTRING);
        !          1097:                                };
        !          1098: #endif
        !          1099:                        goto trap_eol;
        !          1100:                        }
        !          1101:                else if(sync>11) {
        !          1102: #if DEBUG
        !          1103:                        if(dbg_g32r_c){
        !          1104:                                fprintf(stderr,"FILLEOL ");
        !          1105:                                for(si=0;si<sync-11;si++) fprintf(stderr,"0");
        !          1106:                                fprintf(stderr,"+");
        !          1107:                                fprintf(stderr,"%s\n",EOLSTRING);
        !          1108:                                };
        !          1109: #endif
        !          1110:                        goto trap_eol;
        !          1111:                        }
        !          1112:                else {  
        !          1113: #if DEBUG
        !          1114:                        if(dbg_g32r_c){
        !          1115:                                fprintf(stderr,"NOT EOL ");
        !          1116:                                for(si=0;si<sync;si++) fprintf(stderr,"0");
        !          1117:                                fprintf(stderr,"1?");
        !          1118:                                };
        !          1119: #endif
        !          1120:                        sync=0;
        !          1121:                        goto trap_eol_err;
        !          1122:                        };
        !          1123:                break;
        !          1124:            case EOF:  goto trap_eof;  break;
        !          1125:            };
        !          1126:        goto trap_eol;
        !          1127: 
        !          1128: trap_code_err:
        !          1129:        /* unexpected coding sequence:
        !          1130:           'px' holds last decoding context & 'bitv' latest bit value;
        !          1131:           will attempt to resynchronize on next EOL */
        !          1132: #if DEBUG
        !          1133:        if(dbg_g32r_c)fprintf(stderr,"CODERR  %s%d?",
        !          1134:                                t->e[px.tr.s].p,bitv);
        !          1135: #endif
        !          1136:        /* count trailing 0's so far (should be in table) */
        !          1137: #if !NEW_TRAIL
        !          1138:        if(bitv==0) sync=1; else sync=0;
        !          1139:        si=strlen(t->e[px.tr.s].p)-1;
        !          1140:        while(si>=0&&t->e[px.tr.s].p[si]=='0') {sync++; si--;};
        !          1141:        fill = (si<0);  /* all 0's:  may be fill bits */
        !          1142: #else
        !          1143:        if(bitv==0) sync=t->e[px.tr.s].z+1; else sync=t->e[px.tr.s].z;
        !          1144:        fill = (sync>t->e[px.tr.s].l); /* all 0's:  maybe fill bits */
        !          1145: #endif 
        !          1146: #if DEBUG
        !          1147:        if(dbg_trail)err("sync %d fill %d",sync,fill);
        !          1148: #endif
        !          1149: trap_eol_err:
        !          1150:        while(sync<11) {
        !          1151:                switch(bitv=getb(f)) {
        !          1152:                        case 0:  sync++;
        !          1153: #if DEBUG
        !          1154:                                if(dbg_g32r_c) fprintf(stderr,"0");
        !          1155: #endif
        !          1156:                                break;
        !          1157:                        case 1:  sync=0;
        !          1158: #if DEBUG
        !          1159:                                if(dbg_g32r_c) fprintf(stderr,"1");
        !          1160: #endif
        !          1161:                                break;
        !          1162:                        case EOF:  goto trap_eof;  break;
        !          1163:                        };
        !          1164:                };
        !          1165:        /* next `1' will synchronize */
        !          1166:        do {    switch(bitv=getb(f)) {
        !          1167:                        case 0:
        !          1168: #if DEBUG
        !          1169:                                if(dbg_g32r_c) fprintf(stderr,"0");
        !          1170: #endif
        !          1171:                                break;
        !          1172:                        case 1:
        !          1173: #if DEBUG
        !          1174:                                if(dbg_g32r_c) fprintf(stderr,"1");
        !          1175: #endif
        !          1176:                                break;
        !          1177:                        case EOF:  goto trap_eof;  break;
        !          1178:                        };
        !          1179:                }
        !          1180:        while(bitv!=1);
        !          1181: #if DEBUG
        !          1182:        if(dbg_g32r_c) fprintf(stderr," EOL\n");
        !          1183: #endif
        !          1184:        goto trap_eol;
        !          1185: 
        !          1186: trap_eol:      /* come here having seen (and reported) EOL */
        !          1187:        /* learn/check line-length */
        !          1188:        if(a0>=0) crl->len=a0; else crl->len=0;
        !          1189:        if(crl->len==0) {
        !          1190:                /* no pixels coded -- may be the 1st of 6 RTC EOLs */
        !          1191:                /* check suffix 1 bit */
        !          1192:                if((bitv=getb(f))!=1) goto trap_eol_err;
        !          1193:                rtc_eols=1;
        !          1194: #if DEBUG
        !          1195:                if(dbg_g32r_c)fprintf(stderr,"RTC_EOL +1 (%d)\n",rtc_eols);
        !          1196: #endif
        !          1197:                do {    sync=0;  while((bitv=getb(f))==0) sync++;
        !          1198:                        switch(bitv) {
        !          1199:                            case 1:
        !          1200:                                if(sync<11) {
        !          1201: #if DEBUG
        !          1202:                                        if(dbg_g32r_c){
        !          1203:                                                fprintf(stderr,"NOT RTC ");
        !          1204:                                                for(si=0;si<sync;si++)
        !          1205:                                                        fprintf(stderr,"0");
        !          1206:                                                fprintf(stderr,"1?\n");
        !          1207:                                                };
        !          1208: #endif
        !          1209:                                        sync=0;
        !          1210:                                        goto trap_eol_err;
        !          1211:                                        };
        !          1212:                                break;
        !          1213:                            case EOF:  goto trap_eof;  break;
        !          1214:                            };
        !          1215:                        /* check suffix 1 bit */
        !          1216:                        if((bitv=getb(f))!=1) goto trap_eol_err;
        !          1217:                        rtc_eols++;
        !          1218: #if DEBUG
        !          1219:                        if(dbg_g32r_c) {
        !          1220:                                fprintf(stderr,"RTC_EOL ");
        !          1221:                                for(si=0;si<sync;si++) fprintf(stderr,"0");
        !          1222:                                fprintf(stderr,"1+1  (%d)\n",rtc_eols);
        !          1223:                                };
        !          1224: #endif
        !          1225:                        }
        !          1226:                while(rtc_eols<6);
        !          1227:                /* normal RTC */
        !          1228: #if DEBUG
        !          1229:                if(dbg_g32r_c)fprintf(stderr,"RTC\n");
        !          1230: #endif
        !          1231:                return(NULL);
        !          1232:                }
        !          1233:        else if(prl->len==0) {
        !          1234: #if DEBUG
        !          1235:                if(dbg_g32r_c)fprintf(stderr,"LINELEN %d\n",crl->len);
        !          1236: #endif
        !          1237:                }
        !          1238:        else if(crl->len!=prl->len) {
        !          1239:                err("g32_to_rlel: y%d: LINELEN changes c%d != p%d ? (force to %d)",
        !          1240:                        crl->y,crl->len,prl->len,prl->len);
        !          1241:                crl->len = prl->len;
        !          1242:                };
        !          1243:        swap_rl(crl,prl);
        !          1244:        return(prl);
        !          1245: 
        !          1246: trap_eof:
        !          1247: #if DEBUG
        !          1248:        if(dbg_g32r_c) fprintf(stderr,"<EOF>\n");
        !          1249: #endif
        !          1250:        return(NULL);
        !          1251: 
        !          1252:     }
        !          1253: 
        !          1254: /* Translate a sequence of RLE_Line's (describing a binary image)
        !          1255:    into a file (a stream of bits) in CCITT FAX Group 3 (2-D) compression format.
        !          1256:    BOF_to_g32() must be called first;  then call rlel_to_g32() for each line
        !          1257:    (including blank lines); finally, EOF_to_g32() must be called.  Each line's
        !          1258:    EOL and the RTC's first EOL will be padded so they end on a byte boundary.
        !          1259:    */
        !          1260: /* debugging flags:  trace to stderr */
        !          1261: #define dbg_rg32_e (0) /* entry */
        !          1262: #define dbg_rg32_r (0) /* runs */
        !          1263: #define dbg_rg32_s (0) /* bitstrings */
        !          1264: #define rg32_strict (1)        /* 1 is CORRECT: explicitly code the last black pel */
        !          1265: 
        !          1266: #if DEBUG
        !          1267: #define bits_g32(bits) { \
        !          1268:        cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;};  \
        !          1269:        if(dbg_rg32_s) fprintf(stderr,"%s",(bits)); \
        !          1270:        if(dbg_rg32_r) fprintf(stderr," "); \
        !          1271:        }
        !          1272: #else
        !          1273: #define bits_g32(bits) { \
        !          1274:        cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;};  \
        !          1275:        }
        !          1276: #endif
        !          1277: #if DEBUG
        !          1278: #define EOL_g32 { \
        !          1279:        if(dbg_rg32_r) fprintf(stderr,"EOL     "); \
        !          1280:        bits_g32(EOLSTRING); \
        !          1281:        if(dbg_rg32_r) fprintf(stderr,"\n"); \
        !          1282:        }
        !          1283: #else
        !          1284: #define EOL_g32 { \
        !          1285:        bits_g32(EOLSTRING); \
        !          1286:        }
        !          1287: #endif
        !          1288: 
        !          1289: BOF_to_g32(f)
        !          1290:     BITFILE *f;
        !          1291: {   char *cs;
        !          1292:        /* a NOP: no header for Group 3 (2-D) */
        !          1293: #if DEBUG
        !          1294:        if(dbg_rg32_e) fprintf(stderr,"BOF\n");
        !          1295: #endif
        !          1296:        };
        !          1297: 
        !          1298: rlel_to_g32(pl,cl,wid,f)
        !          1299:     RLE_Line *pl;      /* prior "reference" line: if NULL, use 1-D coding on cl */
        !          1300:     RLE_Line *cl;      /* current "coding" line: if NULL, is blank (all white) */
        !          1301:     int wid;           /* width of an output line in pixels */
        !          1302:     BITFILE *f;
        !          1303: {   int runl,codi;
        !          1304:     char *cs,*p01;
        !          1305: #if DEBUG
        !          1306: #define Wrun_g32(rn) { \
        !          1307:        runl=(rn); \
        !          1308:        if(dbg_rg32_r) fprintf(stderr,"W %5d ",runl); \
        !          1309:        while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g32(p01); runl-=2560;}; \
        !          1310:        p01=codewht[codi=rtoi(runl)]; bits_g32(p01); \
        !          1311:        if(codi>=64) {p01=codewht[runl%64]; bits_g32(p01);}; \
        !          1312:        if(dbg_rg32_r) fprintf(stderr,"\n"); \
        !          1313:        }
        !          1314: #else
        !          1315: #define Wrun_g32(rn) { \
        !          1316:        runl=(rn); \
        !          1317:        while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g32(p01); runl-=2560;}; \
        !          1318:        p01=codewht[codi=rtoi(runl)]; bits_g32(p01); \
        !          1319:        if(codi>=64) {p01=codewht[runl%64]; bits_g32(p01);}; \
        !          1320:        }
        !          1321: #endif
        !          1322: #if DEBUG
        !          1323: #define Brun_g32(rn) { \
        !          1324:        runl=(rn); \
        !          1325:        if(dbg_rg32_r) fprintf(stderr,"B %5d ",runl); \
        !          1326:        while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g32(p01); runl-=2560;}; \
        !          1327:        p01=codeblk[codi=rtoi(runl)]; bits_g32(p01); \
        !          1328:        if(codi>=64) {p01=codeblk[runl%64]; bits_g32(p01);}; \
        !          1329:        if(dbg_rg32_r) fprintf(stderr,"\n"); \
        !          1330:        }
        !          1331: #else
        !          1332: #define Brun_g32(rn) { \
        !          1333:        runl=(rn); \
        !          1334:        while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g32(p01); runl-=2560;}; \
        !          1335:        p01=codeblk[codi=rtoi(runl)]; bits_g32(p01); \
        !          1336:        if(codi>=64) {p01=codeblk[runl%64]; bits_g32(p01);}; \
        !          1337:        }
        !          1338: #endif
        !          1339: #if DEBUG
        !          1340: #define V0_g32 { \
        !          1341:        if(dbg_rg32_r) fprintf(stderr,"V0      "); \
        !          1342:        bits_g32(code2d[i2D_V0]); \
        !          1343:        if(dbg_rg32_r) fprintf(stderr,"\n"); \
        !          1344:        }
        !          1345: #else
        !          1346: #define V0_g32 { \
        !          1347:        bits_g32(code2d[i2D_V0]); \
        !          1348:        }
        !          1349: #endif
        !          1350: #if DEBUG
        !          1351: #define VR1_g32 { \
        !          1352:        if(dbg_rg32_r) fprintf(stderr,"VR1     "); \
        !          1353:        bits_g32(code2d[i2D_VR1]); \
        !          1354:        if(dbg_rg32_r) fprintf(stderr,"\n"); \
        !          1355:        }
        !          1356: #else
        !          1357: #define VR1_g32 { \
        !          1358:        bits_g32(code2d[i2D_VR1]); \
        !          1359:        }
        !          1360: #endif
        !          1361: #if DEBUG
        !          1362: #define VR2_g32 { \
        !          1363:        if(dbg_rg32_r) fprintf(stderr,"VR2     "); \
        !          1364:        bits_g32(code2d[i2D_VR2]); \
        !          1365:        if(dbg_rg32_r) fprintf(stderr,"\n"); \
        !          1366:        }
        !          1367: #else
        !          1368: #define VR2_g32 { \
        !          1369:        bits_g32(code2d[i2D_VR2]); \
        !          1370:        }
        !          1371: #endif
        !          1372: #if DEBUG
        !          1373: #define VR3_g32 { \
        !          1374:        if(dbg_rg32_r) fprintf(stderr,"VR3     "); \
        !          1375:        bits_g32(code2d[i2D_VR3]); \
        !          1376:        if(dbg_rg32_r) fprintf(stderr,"\n"); \
        !          1377:        }
        !          1378: #else
        !          1379: #define VR3_g32 { \
        !          1380:        bits_g32(code2d[i2D_VR3]); \
        !          1381:        }
        !          1382: #endif
        !          1383: #if DEBUG
        !          1384: #define VL1_g32 { \
        !          1385:        if(dbg_rg32_r) fprintf(stderr,"VL1     "); \
        !          1386:        bits_g32(code2d[i2D_VL1]); \
        !          1387:        if(dbg_rg32_r) fprintf(stderr,"\n"); \
        !          1388:        }
        !          1389: #else
        !          1390: #define VL1_g32 { \
        !          1391:        bits_g32(code2d[i2D_VL1]); \
        !          1392:        }
        !          1393: #endif
        !          1394: #if DEBUG
        !          1395: #define VL2_g32 { \
        !          1396:        if(dbg_rg32_r) fprintf(stderr,"VL2     "); \
        !          1397:        bits_g32(code2d[i2D_VL2]); \
        !          1398:        if(dbg_rg32_r) fprintf(stderr,"\n"); \
        !          1399:        }
        !          1400: #else
        !          1401: #define VL2_g32 { \
        !          1402:        bits_g32(code2d[i2D_VL2]); \
        !          1403:        }
        !          1404: #endif
        !          1405: #if DEBUG
        !          1406: #define VL3_g32 { \
        !          1407:        if(dbg_rg32_r) fprintf(stderr,"VL3     "); \
        !          1408:        bits_g32(code2d[i2D_VL3]); \
        !          1409:        if(dbg_rg32_r) fprintf(stderr,"\n"); \
        !          1410:        }
        !          1411: #else
        !          1412: #define VL3_g32 { \
        !          1413:        bits_g32(code2d[i2D_VL3]); \
        !          1414:        }
        !          1415: #endif
        !          1416: #if DEBUG
        !          1417: #define PASS_g32 { \
        !          1418:        if(dbg_rg32_r) fprintf(stderr,"PASS    "); \
        !          1419:        bits_g32(code2d[i2D_PASS]); \
        !          1420:        if(dbg_rg32_r) fprintf(stderr,"\n"); \
        !          1421:        }
        !          1422: #else
        !          1423: #define PASS_g32 { \
        !          1424:        bits_g32(code2d[i2D_PASS]); \
        !          1425:        }
        !          1426: #endif
        !          1427: #if DEBUG
        !          1428: #define HORIZ_g32 { \
        !          1429:        if(dbg_rg32_r) fprintf(stderr,"HORIZ   "); \
        !          1430:        bits_g32(code2d[i2D_HORIZ]); \
        !          1431:        if(dbg_rg32_r) fprintf(stderr,"\n"); \
        !          1432:        }
        !          1433: #else
        !          1434: #define HORIZ_g32 { \
        !          1435:        bits_g32(code2d[i2D_HORIZ]); \
        !          1436:        }
        !          1437: #endif
        !          1438: #define detect_a1a2_BW { \
        !          1439:        /* find leftmost black changing pel > a0 */ \
        !          1440:        /* advance cra as far as possible s.t. cra->xe<=a0 */ \
        !          1441:        while((cra+1)<cre && (cra+1)->xe<=a0) cra++; \
        !          1442:        /* look beyond cra, until cr->xs>a0 */ \
        !          1443:        cr=cra; while(cr<cre && (a1=cr->xs)<=a0) cr++; \
        !          1444:        if(cr<cre) a2=cr->xe+1; \
        !          1445:        else a1=a2=wid; \
        !          1446:        }
        !          1447: #define detect_a1a2_WB { \
        !          1448:        /* find leftmost white changing pel > a0 */ \
        !          1449:        /* advance cra as far as possible s.t. cra->xe<=a0 */ \
        !          1450:        while((cra+1)<cre && (cra+1)->xe<=a0) cra++; \
        !          1451:        /* look beyond cra, until cr->xe+1>a0 */ \
        !          1452:        cr=cra;  while(cr<cre && (a1=cr->xe+1)<=a0) cr++; \
        !          1453:        if(cr<cre) { \
        !          1454:                if((cr+1)<cre) a2=(cr+1)->xs; \
        !          1455:                else a2=wid; \
        !          1456:                } \
        !          1457:        else a1=a2=wid; \
        !          1458:        }
        !          1459: #define detect_a1a2 {if(a0_color==DST_white) detect_a1a2_BW else detect_a1a2_WB;}
        !          1460: #define detect_b1b2_BW {\
        !          1461:        /* find leftmost black changing pel > a0 */ \
        !          1462:        /* advance pra as far as possible s.t. pra->xe<=a0 */ \
        !          1463:        while((pra+1)<pre && (pra+1)->xe<=a0) pra++; \
        !          1464:        /* look beyond pra */ \
        !          1465:        pr=pra;  while(pr<pre && (b1=pr->xs)<=a0) pr++; \
        !          1466:        /* move b2 to 1st changing white pel > b1 */ \
        !          1467:        if(pr<pre) b2=pr->xe+1; \
        !          1468:        else b1=b2=wid; \
        !          1469:        }
        !          1470: #define detect_b1b2_WB {\
        !          1471:        /* find leftmost white changing pel > a0 */ \
        !          1472:        /* advance pra as far as possible s.t. pra->xe<=a0 */ \
        !          1473:        while((pra+1)<pre && (pra+1)->xe<=a0) pra++; \
        !          1474:        /* look beyond pra */ \
        !          1475:        pr=pra;  while(pr<pre && (b1=pr->xe+1)<=a0) pr++; \
        !          1476:        /* move b2 to 1st changing black pel > b1 */ \
        !          1477:        if(pr<pre) { \
        !          1478:                if((pr+1)<pre) b2=(pr+1)->xs; \
        !          1479:                else b2=wid; \
        !          1480:                } \
        !          1481:        else b1=b2=wid; \
        !          1482:        }
        !          1483: #define detect_b1b2 {if(a0_color==DST_white) detect_b1b2_BW else detect_b1b2_WB;}
        !          1484: 
        !          1485: #if DEBUG
        !          1486:        if(dbg_rg32_e) err("rlel_to_g32(pl[%d],cl[%d],w%d)",
        !          1487:                                (pl==NULL)? -1: pl->runs,
        !          1488:                                (cl==NULL)? -1: cl->runs,
        !          1489:                                wid);
        !          1490: #endif
        !          1491:        /* fill so that EOL ends on byte boundary */
        !          1492:        padb(f,0,8,EOLLENGTH);
        !          1493: #if DEBUG
        !          1494:        if(dbg_rg32_s) fprintf(stderr,"FILL  +0?");
        !          1495: #endif
        !          1496:        EOL_g32;        /* begin with EOL (sic) */
        !          1497:        if(pl==NULL) /* use 1-D coding for *cl */ {
        !          1498:            int pi;             /* input pixel index on line */
        !          1499:            RLE_Run *rp,*pp,*sp;
        !          1500:                putb(1,f);
        !          1501: #if DEBUG
        !          1502:                if(dbg_rg32_r) fprintf(stderr,"1D_LINE 1\n");
        !          1503: #endif
        !          1504:                if(cl!=NULL&&cl->runs>0) {
        !          1505:                        pi=0;   /* bit to write next */
        !          1506:                        for(sp=(rp=cl->r)+cl->runs; rp<sp; rp++) {
        !          1507:                                Wrun_g32(rp->xs-pi);  pi=rp->xs;
        !          1508:                                Brun_g32(rp->xe-pi+1);  pi=rp->xe+1;
        !          1509:                                };
        !          1510:                        if((--rp)->xe+1<wid) Wrun_g32(wid-rp->xe-1);
        !          1511:                        }
        !          1512:                else Wrun_g32(wid);  /* blank scanline */
        !          1513:                }
        !          1514:        else /* use 2-D coding for *cl */ {
        !          1515:            RLE_Run *cr,*cre,*pr,*pre;  /* into current/prior rle lines */      
        !          1516:            int a0,a1,a2,b1,b2;  /* indices {0,1,...} of pixels */
        !          1517:            DST_color a0_color;  /* a0's color:  same as a2 & b2, opp of a1 & b1 */
        !          1518:            RLE_Run *cra;   /* rightmost in current st xe<=a0 (none: ==cl->r)  */
        !          1519:            RLE_Run *pra;   /* rightmost in prior st xe<=a0 (none: ==pl->r) */
        !          1520:            int a01,a12,a1b1;   /* lengths of runs a0-a1 a1-a2 a1-b1 */
        !          1521:                putb(0,f);
        !          1522: #if DEBUG
        !          1523:                if(dbg_rg32_r) fprintf(stderr,"2D_LINE 0\n");
        !          1524: #endif
        !          1525:                /* start on an imaginary white pixel just to left of margin */
        !          1526:                a0= -1;  a0_color = DST_white;  
        !          1527:                pre = (pra=pl->r) + pl->runs;   /* prior line's runs */
        !          1528:                /* start b1/b2 on prior line's first black pixel, etc;
        !          1529:                   if none, then place off end of line */
        !          1530:                if(pra<pre) {b1=pra->xs; b2=pra->xe+1;} else b1=b2=wid;
        !          1531:                if(cl!=NULL&&cl->runs>0) {
        !          1532:                        cre = (cra=cl->r) + cl->runs;
        !          1533:                        a1=cra->xs;  a2=cra->xe+1;
        !          1534: #if rg32_strict
        !          1535:                        while(a0 < wid) {
        !          1536: #else
        !          1537:                        while(a0 < wid-1) {
        !          1538: #endif
        !          1539:                                /* a0, a1, a2, b1, b2 are as in CCITT Rec T.4 */
        !          1540: #if DEBUG
        !          1541:                                if(dbg_rg32_r)
        !          1542:                                    fprintf(stderr,"f%d(%d,%d,%d) b%d(%d,%d)\n",
        !          1543:                                        cra-(cl->r),a0,a1,a2,pra-(pl->r),b1,b2);
        !          1544: #endif
        !          1545:                                if(b2<a1) /* PASS mode */ {
        !          1546:                                        PASS_g32;
        !          1547:                                        a0=b2;
        !          1548:                                        /* a0-color, a1, & a2 are unchanged */
        !          1549:                                        detect_b1b2;
        !          1550:                                        }
        !          1551:                                else if((a1b1=(a1-b1))<=3 && a1b1>= -3) {
        !          1552:                                        /* VERTICAL mode */
        !          1553:                                        switch(a1b1) {
        !          1554:                                            case -3:  VL3_g32;  break;
        !          1555:                                            case -2:  VL2_g32;  break;
        !          1556:                                            case -1:  VL1_g32;  break;
        !          1557:                                            case 0:  V0_g32;  break;
        !          1558:                                            case 1:  VR1_g32;  break;
        !          1559:                                            case 2:  VR2_g32;  break;
        !          1560:                                            case 3:  VR3_g32;  break;
        !          1561:                                            };
        !          1562:                                        a0=a1;  a0_color=flip_color(a0_color);
        !          1563:                                        detect_a1a2;
        !          1564:                                        detect_b1b2;
        !          1565:                                        }
        !          1566:                                else {  /* HORIZONTAL mode */
        !          1567:                                        HORIZ_g32;
        !          1568:                                        a01=a1-a0; if(a0== -1) a01--;
        !          1569:                                        a12=a2-a1;
        !          1570:                                        if(a0_color==DST_white) {
        !          1571:                                                Wrun_g32(a01);
        !          1572:                                                Brun_g32(a12);
        !          1573:                                                }
        !          1574:                                        else {  Brun_g32(a01);
        !          1575:                                                Wrun_g32(a12);
        !          1576:                                                };
        !          1577:                                        a0=a2;
        !          1578:                                        /* a0_color is unchanged */
        !          1579:                                        detect_a1a2;
        !          1580:                                        detect_b1b2;
        !          1581:                                        };
        !          1582:                                };
        !          1583:                        }
        !          1584:                else /* current line is blank */ {
        !          1585:                        a1=a2=wid;
        !          1586: #if rg32_strict
        !          1587:                        while(a0 < wid) {
        !          1588: #else
        !          1589:                        while(a0 < wid-1) {
        !          1590: #endif
        !          1591:                                /* a0, a1, a2, b1, b2 are as in CCITT Rec. T.4 */
        !          1592: #if DEBUG
        !          1593:                                if(dbg_rg32_r)
        !          1594:                                    fprintf(stderr,"f(%d,%d,%d) b%d(%d,%d)\n",
        !          1595:                                        a0,a1,a2,pra-(pl->r),b1,b2);
        !          1596: #endif
        !          1597:                                if(b2<a1) /* PASS mode */ {
        !          1598:                                        PASS_g32;
        !          1599:                                        a0=b2;
        !          1600:                                        /* a0-color, a1, & a2 are unchanged */
        !          1601:                                        detect_b1b2;
        !          1602:                                        }
        !          1603:                                else if((a1b1=a1-b1)<=3 && a1b1>= -3) {
        !          1604:                                        /* VERTICAL mode */
        !          1605:                                        switch(a1b1) {
        !          1606:                                            case -3:  VL3_g32;  break;
        !          1607:                                            case -2:  VL2_g32;  break;
        !          1608:                                            case -1:  VL1_g32;  break;
        !          1609:                                            case 0:  V0_g32;  break;
        !          1610:                                            case 1:  VR1_g32;  break;
        !          1611:                                            case 2:  VR2_g32;  break;
        !          1612:                                            case 3:  VR3_g32;  break;
        !          1613:                                            };
        !          1614:                                        a0=a1;  a0_color=flip_color(a0_color);
        !          1615:                                        /* a1, & a2 are unchanged */
        !          1616:                                        detect_b1b2;
        !          1617:                                        }
        !          1618:                                else {  /* HORIZONTAL mode */
        !          1619:                                        HORIZ_g32;
        !          1620:                                        a01=a1-a0; if(a0== -1) a01--;
        !          1621:                                        a12=a2-a1;
        !          1622:                                        if(a0_color==DST_white) {
        !          1623:                                                Wrun_g32(a01);
        !          1624:                                                Brun_g32(a12);
        !          1625:                                                }
        !          1626:                                        else {  Brun_g32(a01);
        !          1627:                                                Wrun_g32(a12);
        !          1628:                                                };
        !          1629:                                        a0=a2;
        !          1630:                                        /* a0_color, a1, & a2 are unchanged */
        !          1631:                                        detect_b1b2;
        !          1632:                                        };
        !          1633:                                };
        !          1634:                        };
        !          1635:                };
        !          1636:        }
        !          1637: 
        !          1638: EOF_to_g32(f)
        !          1639:     BITFILE *f;
        !          1640: {   char *cs;
        !          1641:        padb(f,0,8,EOLLENGTH);  /* fill so that EOL ends on byte boundary */
        !          1642: #if DEBUG
        !          1643:        if(dbg_rg32_s) fprintf(stderr,"FILL  +0?");
        !          1644: #endif
        !          1645:        /* write RTC */
        !          1646:        EOL_g32;
        !          1647:        EOL_g32;
        !          1648:        EOL_g32;
        !          1649:        EOL_g32;
        !          1650:        EOL_g32;
        !          1651:        EOL_g32;
        !          1652: #if DEBUG
        !          1653:        if(dbg_rg32_e) fprintf(stderr,"EOF\n");
        !          1654: #endif
        !          1655:        }
        !          1656: 
        !          1657: /* Macro for use within g4_to_rlel, to read one 1-D Modified Huffman coded
        !          1658:    run-length of color C, placing the result in variable V.
        !          1659:    Exceptionally, goto trap_eol, trap_eof, or trap_code_err.
        !          1660:   */
        !          1661: #if DEBUG
        !          1662: #define g4_1d_run(C,V) { \
        !          1663:        run = 0; \
        !          1664:        do {    cx.tr.s = (C); \
        !          1665:                do {    px = cx; \
        !          1666:                        switch(bitv=getb(f)) { \
        !          1667:                            case 0 :  cx.tr=t->e[cx.tr.s].t[0];  break; \
        !          1668:                            case 1 :  cx.tr=t->e[cx.tr.s].t[1];  break; \
        !          1669:                            case EOF :  goto trap_eof;  break; \
        !          1670:                            }; \
        !          1671:                        } \
        !          1672:                while(cx.tr.a==DST_action_NULL); \
        !          1673:                switch(cx.tr.a) { \
        !          1674:                    case DST_EOL : \
        !          1675:                        if(dbg_g4r_c)fprintf(stderr,"EOL     %s\n",EOLSTRING); \
        !          1676:                        goto trap_eol; \
        !          1677:                        break; \
        !          1678:                    case DST_action_ERROR :  goto trap_code_err;  break; \
        !          1679:                    default : \
        !          1680:                        if(dbg_g4r_c)fprintf(stderr,"%s%6d %s%d\n", \
        !          1681:                                ((C)==DST_white)? "W": "B", \
        !          1682:                                cx.tr.a, \
        !          1683:                                t->e[px.tr.s].p, \
        !          1684:                                bitv); \
        !          1685:                        run += cx.tr.a; \
        !          1686:                        break; \
        !          1687:                    }; \
        !          1688:                } \
        !          1689:        while(cx.tr.a>63); \
        !          1690:        (V) = run; \
        !          1691:        }
        !          1692: #else
        !          1693: #define g4_1d_run(C,V) { \
        !          1694:        run = 0; \
        !          1695:        do {    cx.tr.s = (C); \
        !          1696:                do {    px = cx; \
        !          1697:                        switch(bitv=getb(f)) { \
        !          1698:                            case 0 :  cx.tr=t->e[cx.tr.s].t[0];  break; \
        !          1699:                            case 1 :  cx.tr=t->e[cx.tr.s].t[1];  break; \
        !          1700:                            case EOF :  goto trap_eof;  break; \
        !          1701:                            }; \
        !          1702:                        } \
        !          1703:                while(cx.tr.a==DST_action_NULL); \
        !          1704:                switch(cx.tr.a) { \
        !          1705:                    case DST_EOL : \
        !          1706:                        goto trap_eol; \
        !          1707:                        break; \
        !          1708:                    case DST_action_ERROR :  goto trap_code_err;  break; \
        !          1709:                    default : \
        !          1710:                        run += cx.tr.a; \
        !          1711:                        break; \
        !          1712:                    }; \
        !          1713:                } \
        !          1714:        while(cx.tr.a>63); \
        !          1715:        (V) = run; \
        !          1716:        }
        !          1717: #endif
        !          1718: 
        !          1719: /* Translate a stream of bits in CCITT FAX Group 4 compression format, of known
        !          1720:    fixed line-length, into a sequence of RLE_Lines.  Returns one (RLE_Line *)
        !          1721:    on each call (or NULL if EOF or error).  The first pixel (black or white)
        !          1722:    in each g4 line is assigned run index 0.
        !          1723:    WARNING:  the RLE_Line returned must NOT be modified by the caller, since
        !          1724:    it is used to decode the next line. */
        !          1725: RLE_Line *g4_to_rlel(t,f,bof,len)
        !          1726:     DST_table *t;
        !          1727:     BITFILE *f;
        !          1728:     boolean bof;       /* beginning of file */
        !          1729:     int len;           /* line-length in pixels (used only on bof) */
        !          1730: #define dbg_g4r_e (0)  /* trace entry-to / exit-from function */
        !          1731: #define dbg_g4r_r (0)  /* trace each run/EOL/ERR_SYN */
        !          1732: #define dbg_g4r_c (0)  /* trace each Huffman code (or, fill+EOL)*/
        !          1733: #define dbg_g4r_t (0)  /* trace each state-transition */
        !          1734: #define g4r_strict (1) /* 1 is CORRECT: explicitly code the last black pel */
        !          1735: {   static RLE_Line rl0,rl1,*prl,*crl; /* prior, current run-lines */
        !          1736:     RLE_Line *swrl;
        !          1737:     int bitv;                  /* the last-read bit value */
        !          1738:     DST_context cx,px;         /* the current/prior decoding context */
        !          1739:     RLE_Run *cr,*pr,*pre;      /* into current/prior rle lines */      
        !          1740:     RLE_Run *pra0;             /* rightmost in prior line with xe<=a0
        !          1741:                                   (if none: prl->r) */
        !          1742:     int run,sync,si,rtc_eols;
        !          1743:     /* pixel indices (0,1,...):  current-line a*; prior-line b*.
        !          1744:        a0 is the index of the most recently completely encoded bit */
        !          1745:     int a0,a1,a2,b1,b2;        
        !          1746:     DST_color a0_color;  /* a0's color:  same as a2 & b2, opposite of a1 & b1 */
        !          1747:     int a01,a12;       /* lengths of runs a0-a1 & a1-a2 */
        !          1748: #define g4_first_color (DST_white)     /* color of 1st run in each line */
        !          1749: #define g4_negative (0)                /* if 1, invert Black/White on output */
        !          1750: #define swap_rl(f,b) {swrl=(f); (f)=(b); (b)=swrl;}
        !          1751: /* detect b1 & b2:  sensitive to a0, a0_color, and prior runs *pr *(pr+1) */
        !          1752: #define g4r_find_Bb1Wb2 { \
        !          1753:        /* find 1st black changing pel>a0 */ \
        !          1754:        /* advance pra0 as far as possible s.t. pra0->xe<=a0 */ \
        !          1755:        while((pra0+1)<pre && (pra0+1)->xe<=a0) pra0++; \
        !          1756:        /* look beyond pra0 */ \
        !          1757:        pr=pra0;  while(pr<pre && (b1=pr->xs)<=a0) pr++; \
        !          1758:        /* move b2 to 1st changing white pel > b1 */ \
        !          1759:        if(pr<pre) b2=pr->xe+1; \
        !          1760:        else b1=b2=prl->len; \
        !          1761:        }
        !          1762: #define g4r_find_Wb1Bb2 { \
        !          1763:        /* find 1st white changing pel>a0 */ \
        !          1764:        /* advance pra0 as far as possible s.t. pra0->xe<=a0 */ \
        !          1765:        while((pra0+1)<pre && (pra0+1)->xe<=a0) pra0++; \
        !          1766:        /* look beyond pra0 */ \
        !          1767:        pr=pra0;  while(pr<pre && (b1=pr->xe+1)<=a0) pr++; \
        !          1768:        /* move b2 to 1st changing black pel > b1 */ \
        !          1769:        if(pr<pre) { \
        !          1770:                if((pr+1)<pre) b2=(pr+1)->xs; \
        !          1771:                else b2=prl->len; \
        !          1772:                } \
        !          1773:        else b1=b2=prl->len; \
        !          1774:        }
        !          1775: #define g4r_find_b1b2 { \
        !          1776:        if(a0_color==DST_white) g4r_find_Bb1Wb2 else g4r_find_Wb1Bb2; \
        !          1777:        if(b1<=a0) err("g4_to_rlel: y%d: b1 %d <= a0 %d ?",crl->y,a0,b1); \
        !          1778:        }
        !          1779: 
        !          1780:        if(bof){/* initial reference line is all white, of known length */
        !          1781:                prl= &rl0;  prl->y= -1;  prl->len=len;  prl->runs=0;
        !          1782:                /* initial coding line has y-coordinate 0 */
        !          1783:                crl= &rl1;  crl->y=0;  crl->len=0;  crl->runs=0;
        !          1784:                }
        !          1785:        else crl->y = prl->y + 1;
        !          1786: #if DEBUG
        !          1787:        if(dbg_g4r_e)
        !          1788:                fprintf(stderr,
        !          1789:                        "g4_to_rlel(t,f,bof%d,len%d) y%d,l%d\n",
        !          1790:                        bof,len,prl->y,prl->len);
        !          1791: #endif
        !          1792:        
        !          1793:        pre = (pra0=pr=prl->r) + prl->runs;     /* prior line */
        !          1794:        crl->runs=0;  cr=crl->r-1;              /* current line */
        !          1795:        /* start on an imaginary white pixel just to left of margin */
        !          1796:        a0= -1;  a0_color = DST_white;
        !          1797: #if DEBUG
        !          1798:        a1=a2=b1=b2=0;  /* immaterial; looks better when debugging */
        !          1799: #endif
        !          1800: 
        !          1801:        /* start b1/b2 on prior line's first black pixel, etc;
        !          1802:           if none, then place off end of line */
        !          1803:        if(pr<pre) {b1=pr->xs; b2=pr->xe+1;} else b1=b2=prl->len;
        !          1804:        /* parse a sequence of 2D codes... */
        !          1805:        while(T/* exit only via 'goto trap_X' */) {
        !          1806:                /* a0, a1, a2, b1, b2 are as defined in CCITT Rec. T.6 */
        !          1807: #if DEBUG
        !          1808:                if(dbg_g4r_r)
        !          1809:                        fprintf(stderr,"a(%d,%d,%d) b(%d,%d)\n",a0,a1,a2,b1,b2);
        !          1810: #endif
        !          1811:                cx.tr.s = DST_2d;  cx.tr.a = DST_action_NULL;
        !          1812: #if DEBUG
        !          1813:                if(dbg_g4r_t)fprintf(stderr,"(%d,%d)\n",cx.tr.s,cx.tr.a);
        !          1814: #endif
        !          1815:                do {    switch(bitv=getb(f)) {
        !          1816:                            case 0 :
        !          1817:                            case 1 :
        !          1818:                                cx.tr=t->e[cx.tr.s].t[bitv];
        !          1819:                                break;
        !          1820:                            case EOF:  goto trap_eof;  break;
        !          1821:                            };
        !          1822: #if DEBUG
        !          1823:                        if(dbg_g4r_t)fprintf(stderr,"%d->(%d,%d)\n",
        !          1824:                                        bitv,cx.tr.s,cx.tr.a);
        !          1825: #endif
        !          1826:                        }
        !          1827:                while(cx.tr.a==DST_action_NULL);
        !          1828: #if DEBUG
        !          1829:                if(dbg_g4r_t)fprintf(stderr,"%s %04d  %s0\n",
        !          1830:                        (cx.c==DST_white)? "W": "B",
        !          1831:                        cx.tr.s,
        !          1832:                        t->e[cx.tr.s].p);
        !          1833: #endif
        !          1834:                switch(cx.tr.a) {
        !          1835:                    case i2D_V0:
        !          1836: #if DEBUG
        !          1837:                        if(dbg_g4r_c)
        !          1838:                                fprintf(stderr,"V0      %s\n",code2d[cx.tr.a]);
        !          1839: #endif
        !          1840:                        a1=b1;
        !          1841:                        /* interpret (a0,a1-1] */
        !          1842:                        if(a0_color==DST_black) cr->xe=a1-1;
        !          1843:                        /* move a0 to a1 */
        !          1844:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !          1845:                        a0_color = flip_color(a0_color);
        !          1846:                        /* interpret a0 */
        !          1847:                        if(a0_color==DST_black) {
        !          1848:                                if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
        !          1849:                                        err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
        !          1850:                                                crl->y,crl->runs,cr->xs,cr->xe);
        !          1851:                                crl->runs++;  (++cr)->xs = a0;  cr->xe = a0;
        !          1852:                                };
        !          1853: #if !g4r_strict
        !          1854:                        if(a0==prl->len-1)
        !          1855:                                { a0++;  goto trap_expecting_eol; };
        !          1856: #endif
        !          1857:                        g4r_find_b1b2;
        !          1858:                        break;
        !          1859:                    case i2D_VR1:
        !          1860: #if DEBUG
        !          1861:                        if(dbg_g4r_c)
        !          1862:                                fprintf(stderr,"VR1     %s\n",code2d[cx.tr.a]);
        !          1863: #endif
        !          1864:                        a1=b1+1;
        !          1865:                        /* encode a0 to a1-1 */
        !          1866:                        if(a0_color==DST_black) cr->xe=a1-1;
        !          1867:                        /* move a0 to a1 */
        !          1868:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !          1869:                        a0_color = flip_color(a0_color);
        !          1870:                        /* encode a0 */
        !          1871:                        if(a0_color==DST_black) {
        !          1872:                                if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
        !          1873:                                        err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
        !          1874:                                                crl->y,crl->runs,cr->xs,cr->xe);
        !          1875:                                crl->runs++;  (++cr)->xs = a0;  cr->xe = a0;
        !          1876:                                };
        !          1877: #if !g4r_strict
        !          1878:                        if(a0==prl->len-1)
        !          1879:                                { a0++;  goto trap_expecting_eol; };
        !          1880: #endif
        !          1881:                        g4r_find_b1b2;
        !          1882:                        break;
        !          1883:                    case i2D_VR2:
        !          1884: #if DEBUG
        !          1885:                        if(dbg_g4r_c)
        !          1886:                                fprintf(stderr,"VR2     %s\n",code2d[cx.tr.a]);
        !          1887: #endif
        !          1888:                        a1=b1+2;
        !          1889:                        /* encode a0 to a1-1 */
        !          1890:                        if(a0_color==DST_black) cr->xe=a1-1;
        !          1891:                        /* move a0 to a1 */
        !          1892:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !          1893:                        a0_color = flip_color(a0_color);
        !          1894:                        /* encode a0 */
        !          1895:                        if(a0_color==DST_black) {
        !          1896:                                if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
        !          1897:                                        err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
        !          1898:                                                crl->y,crl->runs,cr->xs,cr->xe);
        !          1899:                                crl->runs++;  (++cr)->xs = a0;  cr->xe = a0;
        !          1900:                                };
        !          1901: #if !g4r_strict
        !          1902:                        if(a0==prl->len-1)
        !          1903:                                { a0++;  goto trap_expecting_eol; };
        !          1904: #endif
        !          1905:                        g4r_find_b1b2;
        !          1906:                        break;
        !          1907:                    case i2D_VR3:
        !          1908: #if DEBUG
        !          1909:                        if(dbg_g4r_c)
        !          1910:                                fprintf(stderr,"VR3     %s\n",code2d[cx.tr.a]);
        !          1911: #endif
        !          1912:                        a1=b1+3;
        !          1913:                        /* encode a0 to a1-1 */
        !          1914:                        if(a0_color==DST_black) cr->xe=a1-1;
        !          1915:                        /* move a0 to a1 */
        !          1916:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !          1917:                        a0_color = flip_color(a0_color);
        !          1918:                        /* encode a0 */
        !          1919:                        if(a0_color==DST_black) {
        !          1920:                                if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
        !          1921:                                        err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
        !          1922:                                                crl->y,crl->runs,cr->xs,cr->xe);
        !          1923:                                crl->runs++;  (++cr)->xs = a0;  cr->xe = a0;
        !          1924:                                };
        !          1925: #if !g4r_strict
        !          1926:                        if(a0==prl->len-1)
        !          1927:                                { a0++;  goto trap_expecting_eol; };
        !          1928: #endif
        !          1929:                        g4r_find_b1b2;
        !          1930:                        break;
        !          1931:                    case i2D_VL1:
        !          1932: #if DEBUG
        !          1933:                        if(dbg_g4r_c)
        !          1934:                                fprintf(stderr,"VL1     %s\n",code2d[cx.tr.a]);
        !          1935: #endif
        !          1936:                        if((a1=b1-1)<=a0)
        !          1937:                                err("g4_to_rlel: y%d: VL1 a1 %d <= a0 %d ?",
        !          1938:                                        crl->y,a1,a0);
        !          1939:                        /* encode a0 to a1-1 */
        !          1940:                        if(a0_color==DST_black) cr->xe=a1-1;
        !          1941:                        /* move a0 to a1 */
        !          1942:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !          1943:                        a0_color = flip_color(a0_color);
        !          1944:                        /* encode a0 */
        !          1945:                        if(a0_color==DST_black) {
        !          1946:                                if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
        !          1947:                                        err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
        !          1948:                                                crl->y,crl->runs,cr->xs,cr->xe);
        !          1949:                                crl->runs++;  (++cr)->xs = a0;  cr->xe = a0;
        !          1950:                                };
        !          1951: #if !g4r_strict
        !          1952:                        if(a0==prl->len-1)
        !          1953:                                { a0++;  goto trap_expecting_eol; };
        !          1954: #endif
        !          1955:                        g4r_find_b1b2;
        !          1956:                        break;
        !          1957:                    case i2D_VL2:
        !          1958: #if DEBUG
        !          1959:                        if(dbg_g4r_c)
        !          1960:                                fprintf(stderr,"VL2     %s\n",code2d[cx.tr.a]);
        !          1961: #endif
        !          1962:                        if((a1=b1-2)<=a0)
        !          1963:                                err("g4_to_rlel: y%d: VL2 a1 %d <= a0 %d ?",
        !          1964:                                        crl->y,a1,a0);
        !          1965:                        /* encode a0 to a1-1 */
        !          1966:                        if(a0_color==DST_black) cr->xe=a1-1;
        !          1967:                        /* move a0 to a1 */
        !          1968:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !          1969:                        a0_color = flip_color(a0_color);
        !          1970:                        /* encode a0 */
        !          1971:                        if(a0_color==DST_black) { 
        !          1972:                                if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
        !          1973:                                        err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
        !          1974:                                                crl->y,crl->runs,cr->xs,cr->xe);
        !          1975:                                crl->runs++;  (++cr)->xs = a0;  cr->xe = a0;
        !          1976:                                };
        !          1977: #if !g4r_strict
        !          1978:                        if(a0==prl->len-1)
        !          1979:                                { a0++;  goto trap_expecting_eol; };
        !          1980: #endif
        !          1981:                        g4r_find_b1b2;
        !          1982:                        break;
        !          1983:                    case i2D_VL3:
        !          1984: #if DEBUG
        !          1985:                        if(dbg_g4r_c)
        !          1986:                                fprintf(stderr,"VL3     %s\n",code2d[cx.tr.a]);
        !          1987: #endif
        !          1988:                        if((a1=b1-3)<=a0)
        !          1989:                                err("g4_to_rlel: y%d: VL3 a1 %d <= a0 %d ?",
        !          1990:                                        crl->y,a1,a0);
        !          1991:                        /* encode a0 to a1-1 */
        !          1992:                        if(a0_color==DST_black) cr->xe=a1-1;
        !          1993:                        /* move a0 to a1 */
        !          1994:                        a0=a1;  if(a0>=prl->len) goto trap_expecting_eol;
        !          1995:                        a0_color = flip_color(a0_color);
        !          1996:                        /* encode a0 */
        !          1997:                        if(a0_color==DST_black) {
        !          1998:                                if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
        !          1999:                                        err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
        !          2000:                                                crl->y,crl->runs,cr->xs,cr->xe);
        !          2001:                                crl->runs++;  (++cr)->xs = a0;  cr->xe = a0;
        !          2002:                                };
        !          2003: #if !g4r_strict
        !          2004:                        if(a0==prl->len-1)
        !          2005:                                { a0++;  goto trap_expecting_eol; };
        !          2006: #endif
        !          2007:                        g4r_find_b1b2;
        !          2008:                        break;
        !          2009:                    case i2D_PASS:
        !          2010: #if DEBUG
        !          2011:                        if(dbg_g4r_c)
        !          2012:                                fprintf(stderr,"PASS    %s\n",code2d[cx.tr.a]);
        !          2013: #endif
        !          2014:                        /* move a0 to b2; no change of color */
        !          2015:                        a0=b2;  if(a0>=prl->len) goto trap_expecting_eol;
        !          2016:                        if(a0_color==DST_black) cr->xe = a0;
        !          2017: #if !g4r_strict
        !          2018:                        if(a0==prl->len-1)
        !          2019:                                { a0++;  goto trap_expecting_eol; };
        !          2020: #endif
        !          2021:                        g4r_find_b1b2;
        !          2022:                        break;
        !          2023:                    case i2D_HORIZ:
        !          2024: #if DEBUG
        !          2025:                        if(dbg_g4r_c)
        !          2026:                                fprintf(stderr,"HORIZ   %s\n",code2d[cx.tr.a]);
        !          2027: #endif
        !          2028:                        if(a0_color==DST_white) {
        !          2029:                                if(a0<0) a0=0;  /* first run in line starts at 0 */
        !          2030:                                g4_1d_run(DST_white,a01);  a1 = a0 + a01;
        !          2031:                                g4_1d_run(DST_black,a12);  a2 = a1 + a12;
        !          2032:                                if(a12>0) /* Black run of >0 length */ {
        !          2033:                                if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
        !          2034:                                        err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
        !          2035:                                                crl->y,crl->runs,cr->xs,cr->xe);
        !          2036:                                        crl->runs++; (++cr)->xs = a1; cr->xe = a2-1;
        !          2037:                                        };
        !          2038:                                a0 = a2;        /* still white */
        !          2039:                                if(a0>=prl->len) goto trap_expecting_eol;
        !          2040:                                /* encode a0 */
        !          2041: #if !g4r_strict
        !          2042:                                if(a0==prl->len-1)
        !          2043:                                        { a0++;  goto trap_expecting_eol; };
        !          2044: #endif
        !          2045:                                g4r_find_Bb1Wb2;
        !          2046:                                }
        !          2047:                        else {  g4_1d_run(DST_black,a01);  a1 = a0 + a01;
        !          2048:                                g4_1d_run(DST_white,a12);  a2 = a1 + a12;
        !          2049:                                if(a01>0) /* Black run of >0 length */ {
        !          2050:                                        cr->xe = a1 - 1;
        !          2051:                                        }
        !          2052:                                else {  /* 0-length: very peculiar: ignore */
        !          2053:                                        fprintf(stderr,
        !          2054:                                           "g4_to_rlel: HORIZ B%d! W%d - ignore\n",
        !          2055:                                           a01,a12);
        !          2056:                                        cr--; crl->runs--;
        !          2057:                                        };
        !          2058:                                a0 = a2;        /* still black */
        !          2059:                                if(a0>=prl->len) goto trap_expecting_eol;
        !          2060:                                /* encode a0 */
        !          2061:                                crl->runs++;  (++cr)->xs = a0;
        !          2062: #if !g4r_strict
        !          2063:                                if(a0==prl->len-1) {
        !          2064:                                        cr->xe = a0;
        !          2065:                                        a0++;
        !          2066:                                        goto trap_expecting_eol;
        !          2067:                                        };
        !          2068: #endif
        !          2069:                                g4r_find_Wb1Bb2;
        !          2070:                                };
        !          2071:                        break;
        !          2072:                    case i2D_EOL:
        !          2073: #if DEBUG
        !          2074:                        if(dbg_g4r_c)
        !          2075:                                fprintf(stderr,"EOL     %s\n",code2d[cx.tr.a]);
        !          2076: #endif
        !          2077:                        goto trap_eol;
        !          2078:                        break;
        !          2079:                    case DST_action_ERROR:  goto trap_code_err;  break;
        !          2080:                    };
        !          2081:                };
        !          2082: 
        !          2083: /* come here via goto's: all these traps return() */
        !          2084: 
        !          2085: trap_expecting_eol:    /* come here having detected (computed) end-of-line */
        !          2086:        /* learn/check/correct line-length */
        !          2087:        crl->len = (a0>0)? a0 : 0;
        !          2088:        if(crl->len!=prl->len) {
        !          2089:                err("g4_to_rlel: y%d: LINELEN changes c%d != p%d ? (force to %d)",
        !          2090:                        crl->y,crl->len,prl->len,prl->len);
        !          2091:                crl->len = prl->len;
        !          2092:                };
        !          2093:        swap_rl(crl,prl);
        !          2094: #if DEBUG
        !          2095:        if(dbg_g4r_e)
        !          2096:                fprintf(stderr,
        !          2097:                        "exit g4_to_rlel: expg_eol y%d,l%d\n",
        !          2098:                        prl->y,prl->len);
        !          2099: #endif
        !          2100:        return(prl);
        !          2101: 
        !          2102: trap_eol:  /* come here having seen an EOL code (rare in Group 4) */
        !          2103:        /* It must be the first of two EOL codes making up the EOB signal */
        !          2104:        /* look for 2nd EOL */
        !          2105:        sync=0;  while((bitv=getb(f))==0) sync++;
        !          2106:        switch(bitv) {
        !          2107:            case 1:
        !          2108:                if(sync==11) {
        !          2109: #if DEBUG
        !          2110:                        if(dbg_g4r_c) {
        !          2111:                                fprintf(stderr,"EOB_EOL %s\n",EOLSTRING);
        !          2112:                                fprintf(stderr,"EOB\n");
        !          2113:                                };
        !          2114: #endif
        !          2115:                        }
        !          2116:                else {  
        !          2117: #if DEBUG
        !          2118:                        if(dbg_g4r_c){
        !          2119:                                fprintf(stderr,"NOT EOB ");
        !          2120:                                for(si=0;si<sync;si++)
        !          2121:                                        fprintf(stderr,"0");
        !          2122:                                fprintf(stderr,"1?\n");
        !          2123:                                fprintf(stderr,"ABORT\n");
        !          2124:                                };
        !          2125: #endif
        !          2126:                        };
        !          2127:                break;
        !          2128:            case EOF:  goto trap_eof;  break;
        !          2129:            };
        !          2130: #if DEBUG
        !          2131:        if(dbg_g4r_e) fprintf(stderr,"exit g4_to_rlel: eol\n");
        !          2132: #endif
        !          2133:        return(NULL);
        !          2134: 
        !          2135: trap_code_err:
        !          2136:        /* unexpected coding sequence:
        !          2137:           'px' holds last decoding context & 'bitv' latest bit value;
        !          2138:           will attempt to resynchronize on next EOL */
        !          2139: #if DEBUG
        !          2140:        if(dbg_g4r_c)fprintf(stderr,"CODERR  %s%d? (px.tr.s=%d)\n",
        !          2141:                                t->e[px.tr.s].p,bitv,px.tr.s);
        !          2142: #endif
        !          2143:        err("g4_to_rlel: code error");
        !          2144: #if DEBUG
        !          2145:        if(dbg_g4r_e) fprintf(stderr,"exit g4_to_rlel: code_err\n");
        !          2146: #endif
        !          2147:        return(NULL);
        !          2148: 
        !          2149: trap_eof:
        !          2150: #if DEBUG
        !          2151:        if(dbg_g4r_c) fprintf(stderr,"<EOF>\n");
        !          2152:        if(dbg_g4r_e) fprintf(stderr,"exit g4_to_rlel: eof\n");
        !          2153: #endif
        !          2154:        return(NULL);
        !          2155: 
        !          2156:     }
        !          2157: 
        !          2158: /* Translate a sequence of RLE_Line's (describing a binary image)
        !          2159:    into a file (a stream of bits) in CCITT FAX Group 4 compression format.
        !          2160:    BOF_to_g4() must be called first; then call rlel_to_g4() for each line
        !          2161:    (including blank lines); finally, EOF_to_g4() must be called.  The EOFB
        !          2162:    is padded (suffixed) with 0's to a byte boundary if necessary; no other
        !          2163:    filling or padding is performed.
        !          2164:    */
        !          2165: /* debugging flags:  trace to stderr */
        !          2166: #define dbg_rg4_e (0)  /* entry */
        !          2167: #define dbg_rg4_r (0)  /* runs */
        !          2168: #define dbg_rg4_c (0)  /* codes (bitstrings) */
        !          2169: #define rg4_strict (1) /* 1 is CORRECT: explicitly code the last black pel */
        !          2170: 
        !          2171: #if DEBUG
        !          2172: #define bits_g4(bits) { \
        !          2173:        cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;};  \
        !          2174:        if(dbg_rg4_c) fprintf(stderr,"%s",(bits)); \
        !          2175:        if(dbg_rg4_r) fprintf(stderr," "); \
        !          2176:        }
        !          2177: #else
        !          2178: #define bits_g4(bits) { \
        !          2179:        cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;};  \
        !          2180:        }
        !          2181: #endif
        !          2182: #if DEBUG
        !          2183: #define EOFB_g4 { \
        !          2184:        if(dbg_rg4_r) fprintf(stderr,"EOFB    "); \
        !          2185:        bits_g4(EOFB); \
        !          2186:        if(dbg_rg4_r) fprintf(stderr,"\n"); \
        !          2187:        }
        !          2188: #else
        !          2189: #define EOFB_g4 { \
        !          2190:        bits_g4(EOFB); \
        !          2191:        }
        !          2192: #endif
        !          2193: 
        !          2194: BOF_to_g4(f)
        !          2195:     BITFILE *f;
        !          2196: {   char *cs;
        !          2197:        /* a NOP: no header for Group 4 */
        !          2198: #if DEBUG
        !          2199:        if(dbg_rg4_e) fprintf(stderr,"BOF\n");
        !          2200: #endif
        !          2201:        };
        !          2202: 
        !          2203: rlel_to_g4(pl,cl,wid,f)
        !          2204:     RLE_Line *pl;      /* prior "reference" line */
        !          2205:     RLE_Line *cl;      /* current "coding" line: if NULL, is blank (all white) */
        !          2206:     int wid;           /* width of an output line in pixels */
        !          2207:     BITFILE *f;
        !          2208: {   int runl,codi;
        !          2209:     char *cs,*p01;
        !          2210: #if DEBUG
        !          2211: #define Wrun_g4(rn) { \
        !          2212:        runl=(rn); \
        !          2213:        if(dbg_rg4_r) fprintf(stderr,"W %5d ",runl); \
        !          2214:        while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g4(p01); runl-=2560;}; \
        !          2215:        p01=codewht[codi=rtoi(runl)]; bits_g4(p01); \
        !          2216:        if(codi>=64) {p01=codewht[runl%64]; bits_g4(p01);}; \
        !          2217:        if(dbg_rg4_r) fprintf(stderr,"\n"); \
        !          2218:        }
        !          2219: #else
        !          2220: #define Wrun_g4(rn) { \
        !          2221:        runl=(rn); \
        !          2222:        while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g4(p01); runl-=2560;}; \
        !          2223:        p01=codewht[codi=rtoi(runl)]; bits_g4(p01); \
        !          2224:        if(codi>=64) {p01=codewht[runl%64]; bits_g4(p01);}; \
        !          2225:        }
        !          2226: #endif
        !          2227: #if DEBUG
        !          2228: #define Brun_g4(rn) { \
        !          2229:        runl=(rn); \
        !          2230:        if(dbg_rg4_r) fprintf(stderr,"B %5d ",runl); \
        !          2231:        while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g4(p01); runl-=2560;}; \
        !          2232:        p01=codeblk[codi=rtoi(runl)]; bits_g4(p01); \
        !          2233:        if(codi>=64) {p01=codeblk[runl%64]; bits_g4(p01);}; \
        !          2234:        if(dbg_rg4_r) fprintf(stderr,"\n"); \
        !          2235:        }
        !          2236: #else
        !          2237: #define Brun_g4(rn) { \
        !          2238:        runl=(rn); \
        !          2239:        while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g4(p01); runl-=2560;}; \
        !          2240:        p01=codeblk[codi=rtoi(runl)]; bits_g4(p01); \
        !          2241:        if(codi>=64) {p01=codeblk[runl%64]; bits_g4(p01);}; \
        !          2242:        }
        !          2243: #endif
        !          2244: #if DEBUG
        !          2245: #define V0_g4 { \
        !          2246:        if(dbg_rg4_r) fprintf(stderr,"V0      "); \
        !          2247:        bits_g4(code2d[i2D_V0]); \
        !          2248:        if(dbg_rg4_r) fprintf(stderr,"\n"); \
        !          2249:        }
        !          2250: #else
        !          2251: #define V0_g4 { \
        !          2252:        bits_g4(code2d[i2D_V0]); \
        !          2253:        }
        !          2254: #endif
        !          2255: #if DEBUG
        !          2256: #define VR1_g4 { \
        !          2257:        if(dbg_rg4_r) fprintf(stderr,"VR1     "); \
        !          2258:        bits_g4(code2d[i2D_VR1]); \
        !          2259:        if(dbg_rg4_r) fprintf(stderr,"\n"); \
        !          2260:        }
        !          2261: #else
        !          2262: #define VR1_g4 { \
        !          2263:        bits_g4(code2d[i2D_VR1]); \
        !          2264:        }
        !          2265: #endif
        !          2266: #if DEBUG
        !          2267: #define VR2_g4 { \
        !          2268:        if(dbg_rg4_r) fprintf(stderr,"VR2     "); \
        !          2269:        bits_g4(code2d[i2D_VR2]); \
        !          2270:        if(dbg_rg4_r) fprintf(stderr,"\n"); \
        !          2271:        }
        !          2272: #else
        !          2273: #define VR2_g4 { \
        !          2274:        bits_g4(code2d[i2D_VR2]); \
        !          2275:        }
        !          2276: #endif
        !          2277: #if DEBUG
        !          2278: #define VR3_g4 { \
        !          2279:        if(dbg_rg4_r) fprintf(stderr,"VR3     "); \
        !          2280:        bits_g4(code2d[i2D_VR3]); \
        !          2281:        if(dbg_rg4_r) fprintf(stderr,"\n"); \
        !          2282:        }
        !          2283: #else
        !          2284: #define VR3_g4 { \
        !          2285:        bits_g4(code2d[i2D_VR3]); \
        !          2286:        }
        !          2287: #endif
        !          2288: #if DEBUG
        !          2289: #define VL1_g4 { \
        !          2290:        if(dbg_rg4_r) fprintf(stderr,"VL1     "); \
        !          2291:        bits_g4(code2d[i2D_VL1]); \
        !          2292:        if(dbg_rg4_r) fprintf(stderr,"\n"); \
        !          2293:        }
        !          2294: #else
        !          2295: #define VL1_g4 { \
        !          2296:        bits_g4(code2d[i2D_VL1]); \
        !          2297:        }
        !          2298: #endif
        !          2299: #if DEBUG
        !          2300: #define VL2_g4 { \
        !          2301:        if(dbg_rg4_r) fprintf(stderr,"VL2     "); \
        !          2302:        bits_g4(code2d[i2D_VL2]); \
        !          2303:        if(dbg_rg4_r) fprintf(stderr,"\n"); \
        !          2304:        }
        !          2305: #else
        !          2306: #define VL2_g4 { \
        !          2307:        bits_g4(code2d[i2D_VL2]); \
        !          2308:        }
        !          2309: #endif
        !          2310: #if DEBUG
        !          2311: #define VL3_g4 { \
        !          2312:        if(dbg_rg4_r) fprintf(stderr,"VL3     "); \
        !          2313:        bits_g4(code2d[i2D_VL3]); \
        !          2314:        if(dbg_rg4_r) fprintf(stderr,"\n"); \
        !          2315:        }
        !          2316: #else
        !          2317: #define VL3_g4 { \
        !          2318:        bits_g4(code2d[i2D_VL3]); \
        !          2319:        }
        !          2320: #endif
        !          2321: #if DEBUG
        !          2322: #define PASS_g4 { \
        !          2323:        if(dbg_rg4_r) fprintf(stderr,"PASS    "); \
        !          2324:        bits_g4(code2d[i2D_PASS]); \
        !          2325:        if(dbg_rg4_r) fprintf(stderr,"\n"); \
        !          2326:        }
        !          2327: #else
        !          2328: #define PASS_g4 { \
        !          2329:        bits_g4(code2d[i2D_PASS]); \
        !          2330:        }
        !          2331: #endif
        !          2332: #if DEBUG
        !          2333: #define HORIZ_g4 { \
        !          2334:        if(dbg_rg4_r) fprintf(stderr,"HORIZ   "); \
        !          2335:        bits_g4(code2d[i2D_HORIZ]); \
        !          2336:        if(dbg_rg4_r) fprintf(stderr,"\n"); \
        !          2337:        }
        !          2338: #else
        !          2339: #define HORIZ_g4 { \
        !          2340:        bits_g4(code2d[i2D_HORIZ]); \
        !          2341:        }
        !          2342: #endif
        !          2343: #define detect_a1a2_BW { \
        !          2344:        /* find leftmost black changing pel > a0 */ \
        !          2345:        /* advance cra as far as possible s.t. cra->xe<=a0 */ \
        !          2346:        while((cra+1)<cre && (cra+1)->xe<=a0) cra++; \
        !          2347:        /* look beyond cra, until cr->xs>a0 */ \
        !          2348:        cr=cra; while(cr<cre && (a1=cr->xs)<=a0) cr++; \
        !          2349:        if(cr<cre) a2=cr->xe+1; \
        !          2350:        else a1=a2=wid; \
        !          2351:        }
        !          2352: #define detect_a1a2_WB { \
        !          2353:        /* find leftmost white changing pel > a0 */ \
        !          2354:        /* advance cra as far as possible s.t. cra->xe<=a0 */ \
        !          2355:        while((cra+1)<cre && (cra+1)->xe<=a0) cra++; \
        !          2356:        /* look beyond cra, until cr->xe+1>a0 */ \
        !          2357:        cr=cra;  while(cr<cre && (a1=cr->xe+1)<=a0) cr++; \
        !          2358:        if(cr<cre) { \
        !          2359:                if((cr+1)<cre) a2=(cr+1)->xs; \
        !          2360:                else a2=wid; \
        !          2361:                } \
        !          2362:        else a1=a2=wid; \
        !          2363:        }
        !          2364: #define detect_a1a2 {if(a0_color==DST_white) detect_a1a2_BW else detect_a1a2_WB;}
        !          2365: #define detect_b1b2_BW {\
        !          2366:        /* find leftmost black changing pel > a0 */ \
        !          2367:        /* advance pra as far as possible s.t. pra->xe<=a0 */ \
        !          2368:        while((pra+1)<pre && (pra+1)->xe<=a0) pra++; \
        !          2369:        /* look beyond pra */ \
        !          2370:        pr=pra;  while(pr<pre && (b1=pr->xs)<=a0) pr++; \
        !          2371:        /* move b2 to 1st changing white pel > b1 */ \
        !          2372:        if(pr<pre) b2=pr->xe+1; \
        !          2373:        else b1=b2=wid; \
        !          2374:        }
        !          2375: #define detect_b1b2_WB {\
        !          2376:        /* find leftmost white changing pel > a0 */ \
        !          2377:        /* advance pra as far as possible s.t. pra->xe<=a0 */ \
        !          2378:        while((pra+1)<pre && (pra+1)->xe<=a0) pra++; \
        !          2379:        /* look beyond pra */ \
        !          2380:        pr=pra;  while(pr<pre && (b1=pr->xe+1)<=a0) pr++; \
        !          2381:        /* move b2 to 1st changing black pel > b1 */ \
        !          2382:        if(pr<pre) { \
        !          2383:                if((pr+1)<pre) b2=(pr+1)->xs; \
        !          2384:                else b2=wid; \
        !          2385:                } \
        !          2386:        else b1=b2=wid; \
        !          2387:        }
        !          2388: #define detect_b1b2 {if(a0_color==DST_white) detect_b1b2_BW else detect_b1b2_WB;}
        !          2389: 
        !          2390:     RLE_Run *cr,*cre,*pr,*pre; /* into current/prior rle lines */      
        !          2391:     int a0,a1,a2,b1,b2;         /* indices {0,1,...} of pixels */
        !          2392:     DST_color a0_color;  /* a0's color:  same as a2 & b2, opp of a1 & b1 */
        !          2393:     RLE_Run *cra;   /* rightmost in current st xe<=a0 (none: ==cl->r)  */
        !          2394:     RLE_Run *pra;   /* rightmost in prior st xe<=a0 (none: ==pl->r) */
        !          2395:     int a01,a12,a1b1;  /* lengths of runs a0-a1 a1-a2 a1-b1 */
        !          2396: #if DEBUG
        !          2397:        if(dbg_rg4_e) err("rlel_to_g4(pl[%d],cl[%d],w%d)",
        !          2398:                                (pl==NULL)? -1: pl->runs,
        !          2399:                                (cl==NULL)? -1: cl->runs,
        !          2400:                                wid);
        !          2401: #endif
        !          2402:        /* start on an imaginary white pixel just to left of margin */
        !          2403:        a0= -1;  a0_color = DST_white;  
        !          2404:        pre = (pra=pl->r) + pl->runs;   /* prior line's runs */
        !          2405:        /* start b1/b2 on prior line's first black pixel, etc;
        !          2406:           if none, then place off end of line */
        !          2407:        if(pra<pre) {b1=pra->xs; b2=pra->xe+1;} else b1=b2=wid;
        !          2408:        if(cl!=NULL&&cl->runs>0) {
        !          2409:                cre = (cra=cl->r) + cl->runs;
        !          2410:                a1=cra->xs;  a2=cra->xe+1;
        !          2411: #if rg4_strict
        !          2412:                while( a0 < wid ) {
        !          2413: #else
        !          2414:                while( a0 < wid-1 ) {
        !          2415: #endif
        !          2416:                        /* a0, a1, a2, b1, b2 are as defined in CCITT Rec. T.6 */
        !          2417: #if DEBUG
        !          2418:                        if(dbg_rg4_r)
        !          2419:                            fprintf(stderr,"f%d(%d,%d,%d) b%d(%d,%d)\n",
        !          2420:                                cra-(cl->r),a0,a1,a2,pra-(pl->r),b1,b2);
        !          2421: #endif
        !          2422:                        if(b2<a1) /* PASS mode */ {
        !          2423:                                PASS_g4;
        !          2424:                                a0=b2;
        !          2425:                                /* a0-color, a1, & a2 are unchanged */
        !          2426:                                detect_b1b2;
        !          2427:                                }
        !          2428:                        else if((a1b1=(a1-b1))<=3 && a1b1>= -3) {
        !          2429:                                /* VERTICAL mode */
        !          2430:                                switch(a1b1) {
        !          2431:                                    case -3:  VL3_g4;  break;
        !          2432:                                    case -2:  VL2_g4;  break;
        !          2433:                                    case -1:  VL1_g4;  break;
        !          2434:                                    case 0:  V0_g4;  break;
        !          2435:                                    case 1:  VR1_g4;  break;
        !          2436:                                    case 2:  VR2_g4;  break;
        !          2437:                                    case 3:  VR3_g4;  break;
        !          2438:                                    };
        !          2439:                                a0=a1;  a0_color=flip_color(a0_color);
        !          2440:                                detect_a1a2;
        !          2441:                                detect_b1b2;
        !          2442:                                }
        !          2443:                        else {  /* HORIZONTAL mode */
        !          2444:                                HORIZ_g4;
        !          2445:                                a01=a1-a0; if(a0== -1) a01--;
        !          2446:                                a12=a2-a1;
        !          2447:                                if(a0_color==DST_white) {
        !          2448:                                        Wrun_g4(a01);
        !          2449:                                        Brun_g4(a12);
        !          2450:                                        }
        !          2451:                                else {  Brun_g4(a01);
        !          2452:                                        Wrun_g4(a12);
        !          2453:                                        };
        !          2454:                                a0=a2;
        !          2455:                                /* a0_color is unchanged */
        !          2456:                                detect_a1a2;
        !          2457:                                detect_b1b2;
        !          2458:                                };
        !          2459:                        };
        !          2460:                }
        !          2461:        else /* current line is blank */ {
        !          2462:                a1=a2=wid;
        !          2463: #if rg4_strict
        !          2464:                while( a0 < wid ) {
        !          2465: #else
        !          2466:                while( a0 < wid-1 ) {
        !          2467: #endif
        !          2468:                        /* a0, a1, a2, b1, b2 are as defined in CCITT Rec. T.6 */
        !          2469: #if DEBUG
        !          2470:                        if(dbg_rg4_r)
        !          2471:                            fprintf(stderr,"f(%d,%d,%d) b%d(%d,%d)\n",
        !          2472:                                a0,a1,a2,pra-(pl->r),b1,b2);
        !          2473: #endif
        !          2474:                        if(b2<a1) /* PASS mode */ {
        !          2475:                                PASS_g4;
        !          2476:                                a0=b2;
        !          2477:                                /* a0-color, a1, & a2 are unchanged */
        !          2478:                                detect_b1b2;
        !          2479:                                }
        !          2480:                        else if((a1b1=a1-b1)<=3 && a1b1>= -3) {
        !          2481:                                /* VERTICAL mode */
        !          2482:                                switch(a1b1) {
        !          2483:                                    case -3:  VL3_g4;  break;
        !          2484:                                    case -2:  VL2_g4;  break;
        !          2485:                                    case -1:  VL1_g4;  break;
        !          2486:                                    case 0:  V0_g4;  break;
        !          2487:                                    case 1:  VR1_g4;  break;
        !          2488:                                    case 2:  VR2_g4;  break;
        !          2489:                                    case 3:  VR3_g4;  break;
        !          2490:                                    };
        !          2491:                                a0=a1;  a0_color=flip_color(a0_color);
        !          2492:                                /* a1, & a2 are unchanged */
        !          2493:                                detect_b1b2;
        !          2494:                                }
        !          2495:                        else {  /* HORIZONTAL mode */
        !          2496:                                HORIZ_g4;
        !          2497:                                a01=a1-a0; if(a0== -1) a01--;
        !          2498:                                a12=a2-a1;
        !          2499:                                if(a0_color==DST_white) {
        !          2500:                                        Wrun_g4(a01);
        !          2501:                                        Brun_g4(a12);
        !          2502:                                        }
        !          2503:                                else {  Brun_g4(a01);
        !          2504:                                        Wrun_g4(a12);
        !          2505:                                        };
        !          2506:                                a0=a2;
        !          2507:                                /* a0_color, a1, & a2 are unchanged */
        !          2508:                                detect_b1b2;
        !          2509:                                };
        !          2510:                        };
        !          2511:                };
        !          2512:        }
        !          2513: 
        !          2514: EOF_to_g4(f)
        !          2515:     BITFILE *f;
        !          2516: {   char *cs;
        !          2517:        /* write EOFB */
        !          2518:        EOFB_g4;
        !          2519: #if DEBUG
        !          2520:        if(dbg_rg4_e) fprintf(stderr,"EOF\n");
        !          2521: #endif
        !          2522:        }
        !          2523: 

unix.superglobalmegacorp.com

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