Annotation of researchv10no/cmd/bcp/bcp.c, revision 1.1.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: /*     T. J. ThompsonT - ATT-BL HO - extensions        */
                      7: 
                      8: /* bcp.c - translate among binary image file formats, optionally trimming,
                      9:        shifting, scaling, and rotating the image on the fly.  Scaling is by
                     10:        arbitrary real factors, separately in X & Y.  Rotation is still crude and
                     11:        slow.
                     12:    USAGE:
                     13:        bcp [options...] [I [O]]
                     14:    I/O:
                     15:        If O is omitted, all output is concatenated to stdout.
                     16:        If I is also omitted, all input is read from stdin.
                     17:        If I is a filename, it is the sole input;  but, if it is a directory name,
                     18:        then every leaf of its file tree is processed in turn; and, in this case,
                     19:        if O also is specified, it is forced to become the root directory
                     20:        of an isomorphic tree of output files (this use of Unix file trees
                     21:        may be defeated using compile-time option FILE_TREE).
                     22: 
                     23:        [PROPOSED:  An input file may be a catenation of pages.  These may vary
                     24:        in TYPE and other parameters.  They will all be translated to the same
                     25:        output type, and catenated to one file, each with a complete translated
                     26:        header.  Generally, a complete picfile header must be repeated at the
                     27:        top of each page:  exceptions include TYPE=cdf, which packs pages in its
                     28:        own peculiar way.]
                     29: 
                     30:    OPTIONS:
                     31:        NOTE:  lengths, distances, and pixel indices are assumed to be in
                     32:        units of pixels (scanner units), unless one of "icpPs" is appended,
                     33:        meaning inches, cm, points, picas, or (explicitly) scanner pixels.
                     34:         This applies to option:  -w (seems buggy).
                     35: 
                     36:        -B[io]  read/write bitfile(9.5) format (doesn't use TYPE= header).
                     37:                [doesn't run-length encode yet:  may be bulky.]
                     38:        -M      write TYPE=bitmap format.
                     39:        -P      write Postscript format (only on Suns; by Tim Thompson, ATT-BL HO)
                     40:        -Rx[,y] force output resolutions to x,y (overrides -xX[,Y]) (pixels/inch).
                     41:                Requires a RES=X Y line in the header.
                     42:        -R=     Force the output resolution to be equal to the greater of
                     43:                the input resolutions.
                     44:        -S      write Sun rasterfile format (only on Suns; by Tim Thompson,
                     45:                ATT-BL HO)
                     46:        -Tt     when reading TYPE=dump, binarize the image by thresholding each
                     47:                pixel value as follows:  (pixel<t)? black: white. (default: -T128)
                     48:        -Ww     shrink-wrap output around black artwork, surrounding it with equal
                     49:                margins of width w (pixels), then translate so that the left-top
                     50:                corner of the margin box is at 0,0 (works only with TYPE=document-
                     51:                image input). (w must be >= 0)
                     52:        -Zx[,y] set input resolution to RES=x y (overriding existing RES, if any)
                     53:        -b      write binary format (TYPE=binary)
                     54:        -d?     trace to stderr:
                     55:                -dR     comment on any change in resolution
                     56:                -dc     point out oddities in cdf files which are, by default,
                     57:                        silently corrected
                     58:                -dh     file headers (a good first debugging step)
                     59:                -dm     margins
                     60:                -dr     runs (exhaustive, voluminous)
                     61:                -ds     status and summary statistics (brief)
                     62:        -g31    write CCITT FAX Group 3 1-dim encoding
                     63:          -31     ditto
                     64:        -g32    write CCITT FAX Group 3 2-dim encoding (see also -k option)
                     65:          -32     ditto
                     66:        -g4     write CCITT FAX Group 4 encoding (the default output format)
                     67:          -4      ditto
                     68:        -kK     set the 'k' for g32 encoding on output (default: -k4)
                     69:        -oX,Y   offset the result by X,Y (merely shift the bounding box)
                     70:        -p      write TYPE=dump NCHAN=1 format; input binary pixels
                     71:                are mapped to grey as follows: (pixel==white)? 255: 0.
                     72:        -r      write rle format (this is Pavlidis' obsolescent OCR format) 
                     73:        -t[lrbN] top of the page is really at the left/right/bottom;
                     74:                after all other transformations are carried out, the image
                     75:                will be rotated to bring the real top of page to the top.
                     76:                By arbitrary convention, the top-left corner of the rotated
                     77:                image will be equal to the top-left corner of the image
                     78:                resulting from all the other transformations.
                     79:                [UNFINISHED, UNDER DEVELOPMENT:  -tr & -tb; -tN, where N is a
                     80:                numeric string, is interpreted as a counterclockwise rotation by
                     81:                N degrees: for now, only handle +/-20 degrees.  The present code
                     82:                for -tN is slow and subject to aliasing.]
                     83:        -v      reverse video:  swap black and white
                     84:        -wL,T,R,B  specify window to select:
                     85:                (L,T) is the left-top (origin) and (R,B) the OPEN right-bottom
                     86:                corner (i.e. the corner coordinates are not included.)   A '%'
                     87:                argument defaults to the input window parameter.
                     88:                [NOTE: since non-zero L,T windows are still not everywhere well
                     89:                supported (by pcp, met, etc), it might be best to shift the
                     90:                new L,T to 0,0 on output -- but this is not done now.]
                     91:        -xX[,Y] expansion factor(s), horizontally and vertically;
                     92:                if only one is specified, they are assumed equal
                     93:                (default: -x1.0,1.0)  May be overridden by -Rx[,y].
                     94:                Requires a RES=X Y line in the header.
                     95: DESCRIPTION
                     96:         This translates among these formats of binary images:
                     97:    ccitt-g31, ccitt-g32, ccitt-g4, picture (TYPE=dump NCHAN=1), binary, rle, 
                     98:    bitfile(9.5), cdf, Sun rasterfile (TYPE=bitmap), and Postscript.  All require
                     99:    a TYPE= header in picfile format (see below), except bitfile(9.5) (as a result,
                    100:    to read these, must use special option: -Bi).  Most require WINDOW=ox oy cx cy
                    101:    and RES=x y header lines also.
                    102:        Optionally, the image may be modified on the fly by the following
                    103:    operations performed in this order:
                    104:        trimming - a subset of the input image is selected (-w option)
                    105:        shifting - the origin is shifted (-o)
                    106:        scaling - real scaling factors are applied, in X & Y separately (-x, -R)
                    107:        rotation - by 90, 180, 270 degrees - UNDER DEVELOPMENT (-t option)
                    108:        reverse-video - swap black and white (-v option)
                    109:    Note that scaling changes the effective digitizing resolution by arbitrary
                    110:    real factors (expansion or contraction), in X and Y separately.  Presently,
                    111:    this is accomplished naively by replication or deletion of pixels.  If it is
                    112:    ever desired to apply more interesting image-processing techniques (such as
                    113:    smoothing and resampling), the required changes may be safely confined to
                    114:    functions transform_rlels() (in bcp.c) & transform_rlel() (in rlelib.c).
                    115:    Accepts TYPE=document-image (or TYPE=dim), flattening its hierarchy,
                    116:    and writes it out as a single page image.
                    117: PICFILE FORMAT (briefly summarized; see picture(5))
                    118:    Each picture file comprises an ASCII header followed by binary data.
                    119:    The header is terminated by two newlines (an empty line).  A typical header is:
                    120:         TYPE=ccitt-g4
                    121:         WINDOW=0 0 640 480
                    122:         RES=300 300
                    123:                        (note the final empty line)
                    124:    TYPE must come first.  The other lines may come in any order.  WINDOW gives
                    125:    the x,y coordinates of the upper left corner (inclusive) and lower right
                    126:    corners (exclusive).  Typically, an image of WxH pixels will be described
                    127:    by WINDOW=0 0 W H.  RES=X Y gives the digitizing resolution horizontally and
                    128:    vertically, in integral pixels/inch.  Supported TYPEs include:
                    129: 
                    130:    dump     A two-dimensional array of pixel structures.  NCHAN=1 is required:
                    131:            one byte per pixel.  On input, the grey pixel values are thresholded
                    132:            to binary (see option -T).  On output, black is 0 and white is 255.
                    133: 
                    134:    bitmap   One bit/pixel, packed into bytes high-order bit first.  Black is `1'.
                    135:            Each horizontal row is padded to a 16-bit boundary with `0'.
                    136:            (This is identical to Sun rasterfile format, except for the ASCII
                    137:            header.)
                    138: 
                    139:    ccitt-g4 CCITT FAX Group 4 compressed image.  Similarly, ccitt-g31 means
                    140:            Group 3/1-D and ccitt-g32 means Group 3/2-D.
                    141: 
                    142:    (Obsolescent 112 formats:
                    143:     rle            A run-length coding, better for binary images (see rle.h).
                    144:     binary  1 bit/pixel, packed into bytes low-order bit first.  Black is `1'.
                    145:            Each horizontal row is padded to a full byte with `0'.)
                    146: 
                    147:     NOTE:  bitfile(9.5) doesn't use an ASCII header.
                    148: 
                    149:    (Odd formats in use outside 112, sometimes very heavily:
                    150:     cdf            supported on input only, and only the first page of several.
                    151:     tiff    not yet supported.)
                    152: 
                    153: IMPLEMENTATION STATUS
                    154:         CCITT FAX ``uncompressed'' (or, ``transparent'') mode is not implemented,
                    155:    either while encoding or decoding.
                    156:        Cdf is an input-only option;  Sun rasterfile and Postscript are output-only options.
                    157:    Postscript output is useful only for very small images.
                    158:         Rotations are only partially implemented, and are slow.
                    159: 
                    160: KNOWN BUGS (30 May 89)
                    161:        WINDOW=OX OY CX CY where OX or OY are non-zero is not handled correctly
                    162:    for every combination of file types.
                    163:        Unit gets passed wrongly to vto_scoor().
                    164:        Rle can't be both inout and output (design flaw: they share a buffer).
                    165:        Beware off-by-one errors (top or bottom line omitted); has not been
                    166:    carefully checked for all file type combinations.
                    167: 
                    168: AUTHORS
                    169:        Dec 1988 - Henry S. Baird (AT&T Bell Labs MH) - first working draft
                    170:        Mar 1989 - Tim Thompson (BL HO) - extensions for SunOS, bug fixes, etc
                    171: */
                    172: 
                    173: #include <stdio.h>
                    174: #include <string.h>
                    175: #include <ctype.h>
                    176: #include "CPU.h"
                    177: #define MAIN 1
                    178: #include "stdocr.h"
                    179: #include "rle.h"
                    180: #include "pic.h"
                    181: #include "Text.h"
                    182:    /* Ugly stubs just to prevent Text.h dragging in many other *.h & *.o files */
                    183:    Bfeats *alloc_bfeats(){}; free_bfeats(){}; Bfeats *dup_bfeats(){};
                    184:    fwrb_bfeats(){}; frdb_bfeats(){}; fix_lag(){}; char *classid_toa(){};
                    185: #include "Bitmap.h"
                    186: #include "CCITT.h"
                    187: #include "bitio.h"
                    188: #if FILE_TREE
                    189: #include "Path.h"
                    190: #endif
                    191: #define CMDNAME "bcp"
                    192: #include "abort.h"
                    193: 
                    194: double atof(),sin(),cos();
                    195: char *strchr();
                    196: 
                    197: /* Runtime options values */
                    198: static struct {
                    199:        boolean from_bitfile;   /* -Bi */
                    200:        boolean to_bitfile;     /* -Bo */
                    201:        boolean to_bitmap;      /* -M */
                    202:        boolean to_g31;         /* -g31 or -31 */
                    203:        boolean to_g32;         /* -g32 or -32 */
                    204:        boolean to_g4;          /* -g4 or -4 */
                    205:        boolean to_rle;         /* -r */
                    206:        boolean to_bin;         /* -b */
                    207:        boolean to_pic;         /* -p */
                    208:        boolean to_post;        /* -P */
                    209:        boolean to_rast;        /* -S */
                    210:        boolean omit_hdr;       /* -O */
                    211:        Sp out_res;             /* -R (-1 = unspecified; -2 = force-equal) */
                    212:        Scoor shrinkwrap;       /* -W (-1 = unspecified) */
                    213:        Sp in_res;              /* -Z (SHRT_MIN,SHRT_MIN = unspecified) */
                    214:        int g32_k;              /* -k */
                    215:        int metheus;            /* -m */
                    216:        Sp offset;              /* -o */
                    217:        boolean dbg_any;
                    218:        boolean dbg_R;          /* -dR */
                    219:        boolean dbg_c;          /* -dc */
                    220:        boolean dbg_h;          /* -dh */
                    221:        boolean dbg_m;          /* -dm */
                    222:        boolean dbg_r;          /* -dr */
                    223:        boolean dbg_s;          /* -ds */
                    224:        boolean show;           /* -s */
                    225:        char top;               /* -tT takes on values: 't', 'l', 'r', 'b', 'a' */
                    226:        float top_angle;        /* -t angular value (set if top=='a') (Radians) */
                    227:        int thresh;             /* -Tt */
                    228:        boolean reverse;        /* -v */
                    229:        char *optarg_l;         /* -w?,,, */
                    230:        char *optarg_t;         /* -w,?,, */
                    231:        char *optarg_r;         /* -w,,?, */
                    232:        char *optarg_b;         /* -w,,,? */
                    233:        Bbx trim;               /* output margins resulting from -w */
                    234:        Pp expand;              /* -x */
                    235:        char *in_fn;
                    236:        char *out_fn;
                    237: } _O = {
                    238:        F, F, F, F, F, T, F, F, F, F, F,
                    239:        F, {-1,-1}, -1, {SHRT_MIN,SHRT_MIN}, 4, -1, Init_Zero_Sp,
                    240:        F, F, F, F, F, F, F, F,
                    241:        't',0.0,
                    242:        128,
                    243:        F,
                    244:        NULL, NULL, NULL, NULL,
                    245:        Init_Max_Bbx,
                    246:        {1.0,1.0},
                    247:        NULL, NULL };   
                    248: 
                    249: parse_args(arc,arv)
                    250:     int arc; char **arv;
                    251: {      /* getopt support */
                    252:        int optch;
                    253:        extern int optind;
                    254:        extern char *optarg;
                    255: 
                    256:     char *metheus_ev,metheus_digit;
                    257:     char *fs;
                    258: 
                    259:        /* default metheus number */
                    260:        if((metheus_ev=(char *)getenv("FB"))!=NULL) {
                    261:                metheus_digit = metheus_ev[(int)strlen(metheus_ev)-1];
                    262:                if((int)isdigit(metheus_digit)) {
                    263:                        _O.metheus = (metheus_digit - '0');
                    264:                        };
                    265:                };
                    266: 
                    267:        while((optch=getopt(arc,arv,"B:MOPR:ST:W:Z:3:4bd:g:k:m:o:prst:vw:x:"))!=EOF)
                    268:                switch(optch) {
                    269:                        case 'B':
                    270:                                switch(*optarg) {
                    271:                                    case 'o':
                    272:                                        _O.to_bitfile = T;
                    273:                                        _O.to_g4 = F;
                    274:                                        break;
                    275:                                    case 'i':
                    276:                                        _O.from_bitfile = T;
                    277:                                        break;
                    278:                                    default:
                    279:                                        abort("option -B%s is illegal",optarg);
                    280:                                        break;
                    281:                                    };
                    282:                                break;
                    283:                        case 'M':  _O.to_bitmap = T;  _O.to_g4 = F; break;
                    284:                        case 'O':  _O.omit_hdr = T; break;
                    285:                        case 'P':
                    286: #if CPU==SUN
                    287:                                _O.to_post = T;  _O.to_g4 = F;
                    288: #else
                    289:                                abort("-P option available only on Suns");
                    290: #endif
                    291:                                break;
                    292:                        case 'R':
                    293:                                if(*optarg=='=') {
                    294:                                        _O.out_res.x = _O.out_res.y = -2;
                    295:                                        fs=NULL;
                    296:                                        }
                    297:                                else if((fs=strtok(optarg,","))!=NULL) {
                    298:                                        if(strcmp(fs,"%")!=0) {
                    299:                                                _O.out_res.x = atoi(fs);
                    300:                                                };
                    301:                                        };
                    302:                                if(fs!=NULL&&(fs=strtok((char *)0,","))!=NULL) {
                    303:                                        if(strcmp(fs,"%")!=0) {
                    304:                                                _O.out_res.y = atoi(fs);
                    305:                                                };
                    306:                                        }
                    307:                                else _O.out_res.y = _O.out_res.x;
                    308:                                break;
                    309:                        case 'S':
                    310: #if CPU==SUN
                    311:                                _O.to_rast = T;  _O.to_g4 = F;
                    312: #else
                    313:                                abort("-S option available only on Suns");
                    314: #endif
                    315:                                break;
                    316:                        case 'T':  _O.thresh=atoi(optarg);  break;
                    317:                        case 'W':  _O.shrinkwrap=atoi(optarg);
                    318:                                if(_O.shrinkwrap<0) {
                    319:                                        err("-W%d must be >=0; force to -W0",
                    320:                                                _O.shrinkwrap);
                    321:                                        _O.shrinkwrap=0;
                    322:                                        };
                    323:                                break;
                    324:                        case 'Z':
                    325:                                if((fs=strtok(optarg,","))!=NULL) {
                    326:                                        if(strcmp(fs,"%")!=0) {
                    327:                                                _O.in_res.x = atoi(fs);
                    328:                                                };
                    329:                                        };
                    330:                                if(fs!=NULL&&(fs=strtok((char *)0,","))!=NULL) {
                    331:                                        if(strcmp(fs,"%")!=0) {
                    332:                                                _O.in_res.y = atoi(fs);
                    333:                                                };
                    334:                                        }
                    335:                                else _O.in_res.y = _O.in_res.x;
                    336:                                break;
                    337:                        case '3':
                    338:                                switch (*optarg) {
                    339:                                    case '1':
                    340:                                        _O.to_g31=T;
                    341:                                        _O.to_g4=F;
                    342:                                        break;
                    343:                                    case '2':
                    344:                                        _O.to_g32=T;
                    345:                                        _O.to_g4=F;
                    346:                                        break;
                    347:                                    default:
                    348:                                        abort("bad option: -g3%s",optarg);
                    349:                                        break;
                    350:                                    };
                    351:                                break;
                    352:                        case '4':  _O.to_g4=T;  break;
                    353:                        case 'b':
                    354:                                _O.to_bin=T;
                    355:                                _O.to_g4=F;
                    356:                                break;
                    357:                        case 'd':
                    358:                                _O.dbg_any=T;
                    359:                                switch(*optarg) {
                    360:                                    case 'R':  _O.dbg_R = T;  break;
                    361:                                    case 'c':  _O.dbg_c = T;  break;
                    362:                                    case 'h':  _O.dbg_h = T;  break;
                    363:                                    case 'm':  _O.dbg_m = T;  break;
                    364:                                    case 'r':  _O.dbg_r = T;  break;
                    365:                                    case 's':  _O.dbg_s = T;  break;
                    366:                                    };
                    367:                                break;
                    368:                        case 'g':  
                    369:                                switch (optarg[0]) {
                    370:                                    case '3':
                    371:                                        switch (optarg[1]) {
                    372:                                            case '1':
                    373:                                                _O.to_g31=T;
                    374:                                                _O.to_g4=F;
                    375:                                                break;
                    376:                                            case '2':
                    377:                                                _O.to_g32=T;
                    378:                                                _O.to_g4=F;
                    379:                                                break;
                    380:                                            default:
                    381:                                                abort("bad option: -g%s",optarg);
                    382:                                                break;
                    383:                                            };
                    384:                                        break;
                    385:                                    case '4':  _O.to_g4=T;  break;
                    386:                                    default:
                    387:                                        abort("bad option: -g%s",optarg);
                    388:                                        break;
                    389:                                    };
                    390:                                break;
                    391:                        case 'k':  _O.g32_k = atoi(optarg); break;
                    392:                        case 'm':  _O.metheus = atoi(optarg); break;
                    393:                        case 'o':
                    394:                                if((fs=strtok(optarg,","))!=NULL) {
                    395:                                        if(strcmp(fs,"%")!=0)
                    396:                                                _O.offset.x = atoi(fs);
                    397:                                        };
                    398:                                if(fs!=NULL&&(fs=strtok((char *)0,","))!=NULL) {
                    399:                                        if(strcmp(fs,"%")!=0)
                    400:                                                _O.offset.y = atoi(fs);
                    401:                                        };
                    402:                                break;
                    403:                        case 'p':
                    404:                                _O.to_pic=T;
                    405:                                _O.to_g4=F;
                    406:                                break;
                    407:                        case 'r':
                    408:                                _O.to_rle = T;
                    409:                                _O.to_g4 = F;
                    410:                                break;
                    411:                        case 's':  _O.show = T;  break;
                    412:                        case 't':  _O.top = *optarg;
                    413:                                if(strchr("0123456789.+-",_O.top)!=NULL) {
                    414:                                        _O.top = 'a';   /* angular value */
                    415:                                        _O.top_angle = atof(optarg)*DtoR;
                    416:                                        };
                    417:                                break;
                    418:                        case 'v':  _O.reverse = T;  break;
                    419:                        case 'w':
                    420:                                if( (fs=strtok(optarg,","))!=NULL
                    421:                                        && strlen(fs)>0 && strcmp(fs,"%")!=0 )
                    422:                                                _O.optarg_l = strdup(fs);
                    423:                                if( fs!=NULL && (fs=strtok((char *)0,","))!=NULL
                    424:                                        && strlen(fs)>0 && strcmp(fs,"%")!=0 )
                    425:                                                _O.optarg_t = strdup(fs);
                    426:                                if( fs!=NULL && (fs=strtok((char *)0,","))!=NULL
                    427:                                        && strlen(fs)>0 && strcmp(fs,"%")!=0 )
                    428:                                                _O.optarg_r = strdup(fs);
                    429:                                if( fs!=NULL && (fs=strtok((char *)0,","))!=NULL
                    430:                                        && strlen(fs)>0 && strcmp(fs,"%")!=0 )
                    431:                                                _O.optarg_b = strdup(fs);
                    432:                                break;
                    433:                        case 'x':
                    434:                                if((fs=strtok(optarg,","))!=NULL) {
                    435:                                        if(strcmp(fs,"%")!=0) {
                    436:                                                if(*fs=='/')
                    437:                                                  _O.expand.x = 1.0/atof(fs+1);
                    438:                                                else _O.expand.x = atof(fs);
                    439:                                                if(_O.expand.x<=0.0)
                    440:                                                  _O.expand.x=1.0;
                    441:                                                };
                    442:                                        };
                    443:                                if(fs!=NULL&&(fs=strtok((char *)0,","))!=NULL) {
                    444:                                        if(strcmp(fs,"%")!=0) {
                    445:                                                if(*fs=='/')
                    446:                                                  _O.expand.y = 1.0/atof(fs+1);
                    447:                                                else _O.expand.y = atof(fs);
                    448:                                                if(_O.expand.y<=0.0)
                    449:                                                  _O.expand.y=1.0;
                    450:                                                };
                    451:                                        }
                    452:                                else _O.expand.y = _O.expand.x;
                    453:                                break;
                    454:                        default: break;
                    455:                        };
                    456:        switch(arc-optind) {
                    457:            case 2:
                    458:                _O.out_fn = strdup(arv[optind+1]);
                    459:            case 1:     
                    460:                _O.in_fn = strdup(arv[optind]);
                    461:            case 0:
                    462:                break;
                    463:            default:
                    464:                abort("<= two filenames expected");
                    465:                break;
                    466:            };
                    467:        if(_O.show&&_O.metheus==-1) {
                    468:                err("FB=/dev/omM not specified, using /dev/om0");
                    469:                _O.metheus = 0;
                    470:                };
                    471:        }
                    472: 
                    473: unimplemented()
                    474: {      abort("unimplemented");
                    475:        }
                    476: 
                    477: typedef struct Copy_arg {
                    478:        boolean bop;    /* beginning of page */
                    479:        PIC_hdr *ph;
                    480:        int wid;        /* bbx_wid(&(ph->bx)) (for speed) */
                    481:        BITFILE *bf;
                    482:        DST_table *tbl; /* for CCITT input */
                    483:        int k;          /* CCITT Group 3 2-D k */
                    484:        int thresh;     /* for input pic files */
                    485:        RLE_Lines rles; /* for TYPE=document-image or TYPE=dim */
                    486:        } Copy_arg;
                    487: #define Init_Copy_arg {T,NULL,INT_MIN,NULL,NULL,4,128,Init_RLE_Lines}
                    488: #if MAIN
                    489: Copy_arg empty_Copy_arg = Init_Copy_arg;
                    490: #else
                    491: extern Copy_arg empty_Copy_arg;
                    492: #endif
                    493: 
                    494: /* SOURCES:  return the next RLE_Line from the given file type, with run indices
                    495:    shifted to lie within [ a->ph->bx.a.x, a->ph->bx.b.x ].
                    496:    **** BUGS:  not all handle non-zero a->ph->bx.a.x yet.
                    497:    */
                    498: 
                    499: /* Handles non-zero a->ph->bx.a.x. */
                    500: RLE_Line *cdf_mrlc_source(a)
                    501:     Copy_arg *a;
                    502: #define dbg_cdf (0)
                    503: {   static RLE_Line rl;
                    504:     int n;     /* no. pixels decoded */
                    505:     int col;   /* color:  0=white, 1=black */
                    506:     int byte;  /* input byte */
                    507:     int nb;    /* no. bytes read for this line */
                    508:     int ni;    /* nibble index: 0=1st (low-order), 1=2nd(high-order) */
                    509:     int nib;   /* current nibble */
                    510:     int mult;  /* multiplier for current nibble */
                    511:     int run;   /* no. pixels in current run */
                    512:     RLE_Run *rp;
                    513: #define toggle_color() {if(col) col=0; else col=1;}
                    514: /* get next byte into `byte' */
                    515: #define getbyte()  { \
                    516:        if((byte=getc(a->ph->fp))==EOF) goto eof; nb++; \
                    517:        if(dbg_cdf) err("byte0x%x",byte); \
                    518:        }
                    519: /* get next nibble into `nib' */
                    520: #define getnib()  { \
                    521:        if(ni) { getbyte();  ni=0;  nib=byte&0x0F; } \
                    522:        else { ni=1;  nib=(byte>>4); } \
                    523:        if(dbg_cdf) err("nib0x%x byte0x%x ni%d",nib,byte,ni); \
                    524:        }
                    525: /* get next run into `run' */
                    526: #define getrun()  { \
                    527:        run=0;  mult=1; \
                    528:        do {getnib();  run += mult * (nib&0x07);  mult *= 8;} while(nib&0x08); \
                    529:        if(dbg_cdf) err("run%d %c",run,((col)? 'B': 'W')); \
                    530:        }
                    531:        a->bop = F;
                    532:        n=0; col=0; ni=1; nb=0; rp=rl.r;
                    533:        do {    getrun();
                    534:                if(col) {/* black run */
                    535:                        if(run>0) { /* ... of >0 length */
                    536:                                rp->xs = a->ph->bx.a.x + n+1;
                    537:                                rp->xe = a->ph->bx.a.x + (n+=run);
                    538:                                if((rp-rl.r)>0 && ((rp-1)->xe >= rp->xs-1) ) {
                    539:                                        if(_O.dbg_c) err("cdf_mrlc_source: abutting black runs [%d,%d] & [%d,%d] - merged",
                    540:                                                (rp-1)->xs,(rp-1)->xe,
                    541:                                                rp->xs,rp->xe );
                    542:                                        /* merge with prior black run */
                    543:                                        (rp-1)->xe = rp->xe;
                    544:                                        }
                    545:                                else rp++;
                    546:                                }
                    547:                        else {  /* zero-length black run */
                    548:                                if( _O.dbg_c && (rp-rl.r)>0 )
                    549:                                        err("cdf_mrlc_source: zero-length black run [%d,%d] in middle of line - ignored",
                    550:                                        n,n);
                    551:                                };
                    552:                        }
                    553:                else {  /* white run */
                    554:                        n+=run;
                    555:                        };
                    556:                toggle_color();
                    557:                }
                    558:        while(n<a->wid);
                    559:        /* read 2 EOL nibbles */
                    560:        getnib(); getnib();
                    561:        rl.runs = rp - rl.r;
                    562:        rl.len = a->wid;
                    563:        if(rl.runs>0 && rl.r[rl.runs-1].xe>=a->wid) {
                    564:                if(_O.dbg_c)
                    565:                    err("cdf_mrlc_source: run [%d,%d] in line of length %d - truncated",
                    566:                        rl.r[rl.runs-1].xs,rl.r[rl.runs-1].xe,a->wid);
                    567:                rl.r[rl.runs-1].xe = a->wid-1;
                    568:                if(rl.r[rl.runs-1].xs>rl.r[rl.runs-1].xe) {
                    569:                        rl.runs--;
                    570:                        };
                    571:                };
                    572:        rl.y = a->ph->cy++;
                    573:        if(_O.dbg_r) nerr_RLE_Line("cdf_source: ",&rl);
                    574:        return(&rl);
                    575: 
                    576: eof:   if(dbg_cdf)
                    577:                err("cdf_mrlc_source: unexpected EOF, input line %d",a->ph->cy);
                    578:        return(NULL);
                    579:        }
                    580: 
                    581: int no_runs_of_page(p)
                    582:     Page *p;
                    583: {   int runs;
                    584:        runs = 0;
                    585:        runs += no_runs_of_blocks(&p->bks);
                    586:        runs += no_runs_of_txtlns(&p->ls);
                    587:        runs += no_runs_of_words(&p->ws);
                    588:        runs += no_runs_of_chars(&p->cs);
                    589:        runs += no_runs_of_blobs(&p->bs);
                    590:        return(runs);
                    591:        }
                    592: 
                    593: int runs_of_page(p,ra,max)
                    594:     Page *p;
                    595:     RLE_Yrun *ra;
                    596:     int max;
                    597: {   int runs;
                    598:        runs = 0;
                    599:        runs += runs_of_blocks(&p->bks,ra,max);
                    600:        runs += runs_of_txtlns(&p->ls,ra+runs,max-runs);
                    601:        runs += runs_of_words(&p->ws,ra+runs,max-runs);
                    602:        runs += runs_of_chars(&p->cs,ra+runs,max-runs);
                    603:        runs += runs_of_blobs(&p->bs,ra+runs,max-runs);
                    604:        return(runs);
                    605:        }
                    606: 
                    607: int no_runs_of_blocks(p)
                    608:     Blocks *p;
                    609: {   int runs;
                    610:     Block *pp,**ppp;
                    611:        runs = 0;
                    612:        if(p->mny>0) for(pp= *(ppp=p->bpa); pp!=NULL; pp= *(++ppp))
                    613:                runs += no_runs_of_block(pp);
                    614:        return(runs);
                    615:        }
                    616: 
                    617: int runs_of_blocks(p,ra,max)
                    618:     Blocks *p;
                    619:     RLE_Yrun *ra;
                    620:     int max;
                    621: {   int runs;
                    622:     Block *pp,**ppp;
                    623:        runs = 0;
                    624:        if(p->mny>0) for(pp= *(ppp=p->bpa); pp!=NULL; pp= *(++ppp))
                    625:                runs += runs_of_block(pp,ra+runs,max-runs);
                    626:        return(runs);
                    627:        }
                    628: 
                    629: int no_runs_of_block(p)
                    630:     Block *p;
                    631: {   int runs;
                    632:        runs = 0;
                    633:        runs += no_runs_of_txtlns(&p->ls);
                    634:        runs += no_runs_of_words(&p->ws);
                    635:        runs += no_runs_of_chars(&p->cs);
                    636:        runs += no_runs_of_blobs(&p->bs);
                    637:        return(runs);
                    638:        }
                    639: 
                    640: int runs_of_block(p,ra,max)
                    641:     Block *p;
                    642:     RLE_Yrun *ra;
                    643:     int max;
                    644: {   int runs;
                    645:        runs = 0;
                    646:        runs += runs_of_txtlns(&p->ls,ra+runs,max-runs);
                    647:        runs += runs_of_words(&p->ws,ra+runs,max-runs);
                    648:        runs += runs_of_chars(&p->cs,ra+runs,max-runs);
                    649:        runs += runs_of_blobs(&p->bs,ra+runs,max-runs);
                    650:        return(runs);
                    651:        }
                    652: 
                    653: int no_runs_of_txtlns(p)
                    654:     Txtlns *p;
                    655: {   int runs;
                    656:     Txtln *pp,**ppp;
                    657:        runs = 0;
                    658:        if(p->mny>0) for(pp= *(ppp=p->lpa); pp!=NULL; pp= *(++ppp))
                    659:                runs += no_runs_of_txtln(pp);
                    660:        return(runs);
                    661:        }
                    662: 
                    663: int runs_of_txtlns(p,ra,max)
                    664:     Txtlns *p;
                    665:     RLE_Yrun *ra;
                    666:     int max;
                    667: {   int runs;
                    668:     Txtln *pp,**ppp;
                    669:        runs = 0;
                    670:        if(p->mny>0) for(pp= *(ppp=p->lpa); pp!=NULL; pp= *(++ppp))
                    671:                runs += runs_of_txtln(pp,ra+runs,max-runs);
                    672:        return(runs);
                    673:        }
                    674: 
                    675: int no_runs_of_txtln(p)
                    676:     Txtln *p;
                    677: {   int runs;
                    678:        runs = 0;
                    679:        runs += no_runs_of_words(&p->ws);
                    680:        runs += no_runs_of_chars(&p->cs);
                    681:        runs += no_runs_of_blobs(&p->bs);
                    682:        return(runs);
                    683:        }
                    684: 
                    685: int runs_of_txtln(p,ra,max)
                    686:     Txtln *p;
                    687:     RLE_Yrun *ra;
                    688:     int max;
                    689: {   int runs;
                    690:        runs = 0;
                    691:        runs += runs_of_words(&p->ws,ra+runs,max-runs);
                    692:        runs += runs_of_chars(&p->cs,ra+runs,max-runs);
                    693:        runs += runs_of_blobs(&p->bs,ra+runs,max-runs);
                    694:        return(runs);
                    695:        }
                    696: 
                    697: int no_runs_of_words(p)
                    698:     Words *p;
                    699: {   int runs;
                    700:     Word *pp,**ppp;
                    701:        runs = 0;
                    702:        if(p->mny>0) for(pp= *(ppp=p->wpa); pp!=NULL; pp= *(++ppp))
                    703:                runs += no_runs_of_word(pp);
                    704:        return(runs);
                    705:        }
                    706: 
                    707: int runs_of_words(p,ra,max)
                    708:     Words *p;
                    709:     RLE_Yrun *ra;
                    710:     int max;
                    711: {   int runs;
                    712:     Word *pp,**ppp;
                    713:        runs = 0;
                    714:        if(p->mny>0) for(pp= *(ppp=p->wpa); pp!=NULL; pp= *(++ppp))
                    715:                runs += runs_of_word(pp,ra+runs,max-runs);
                    716:        return(runs);
                    717:        }
                    718: 
                    719: int no_runs_of_word(p)
                    720:     Word *p;
                    721: {   int runs;
                    722:        runs = 0;
                    723:        runs += no_runs_of_chars(&p->cs);
                    724:        runs += no_runs_of_blobs(&p->bs);
                    725:        return(runs);
                    726:        }
                    727: 
                    728: int runs_of_word(p,ra,max)
                    729:     Word *p;
                    730:     RLE_Yrun *ra;
                    731:     int max;
                    732: {   int runs;
                    733:        runs = 0;
                    734:        runs += runs_of_chars(&p->cs,ra+runs,max-runs);
                    735:        runs += runs_of_blobs(&p->bs,ra+runs,max-runs);
                    736:        return(runs);
                    737:        }
                    738: 
                    739: int no_runs_of_chars(p)
                    740:     Chars *p;
                    741: {   int runs;
                    742:     Char *pp,**ppp;
                    743:        runs = 0;
                    744:        if(p->mny>0) for(pp= *(ppp=p->cpa); pp!=NULL; pp= *(++ppp))
                    745:                runs += no_runs_of_char(pp);
                    746:        return(runs);
                    747:        }
                    748: 
                    749: int runs_of_chars(p,ra,max)
                    750:     Chars *p;
                    751:     RLE_Yrun *ra;
                    752:     int max;
                    753: {   int runs;
                    754:     Char *pp,**ppp;
                    755:        runs = 0;
                    756:        if(p->mny>0) for(pp= *(ppp=p->cpa); pp!=NULL; pp= *(++ppp))
                    757:                runs += runs_of_char(pp,ra+runs,max-runs);
                    758:        return(runs);
                    759:        }
                    760: 
                    761: int no_runs_of_blobs(p)
                    762:     Blobs *p;
                    763: {   int runs;
                    764:     Blob *pp,**ppp;
                    765:        runs = 0;
                    766:        if(p->mny>0) for(pp= *(ppp=p->bpa); pp!=NULL; pp= *(++ppp))
                    767:                runs += pp->runs;
                    768:        return(runs);
                    769:        }
                    770: 
                    771: int runs_of_blobs(p,ra,max)
                    772:     Blobs *p;
                    773:     RLE_Yrun *ra;
                    774:     int max;
                    775: {   int runs;
                    776:     Blob *pp,**ppp;
                    777:        runs = 0;
                    778:        if(p->mny>0) for(pp= *(ppp=p->bpa); pp!=NULL; pp= *(++ppp))
                    779:                runs += runs_of_blob(pp,ra+runs,max-runs);
                    780:        return(runs);
                    781:        }
                    782: 
                    783: /* ascending lexicographic order on y,xs */
                    784: int local_rn_asc(r1,r2)
                    785:    RLE_Yrun *r1,*r2;
                    786: {      if(r1->y < r2->y) return(-1);
                    787:        else if(r1->y==r2->y) {
                    788:                if(r1->xs < r2->xs) return(-1);
                    789:                else if (r1->xs == r2->xs) return(0);
                    790:                else return(1);
                    791:                }
                    792:        else return(1);
                    793:        }
                    794: 
                    795: RLE_Lines *rle_lines_of_page(pgp)
                    796:     Page *pgp;
                    797: {   static RLE_Lines rls;
                    798:     int no_runs,cy,ri;
                    799:     RLE_Yrun *ra,*cr;
                    800:     RLE_Run *lr;
                    801:     RLE_Line *cl;
                    802:        /* count runs */
                    803:        no_runs = no_runs_of_page(pgp);
                    804:        if(_O.dbg_r) err("no_runs %d",no_runs);
                    805:        /* allocate runs array */
                    806:        if((ra=(RLE_Yrun *)malloc(no_runs*sizeof(RLE_Yrun)))==NULL)
                    807:                abort("rle_lines_of_page: can't malloc ra[%d]",no_runs);
                    808:        runs_of_page(pgp,ra,no_runs);
                    809:        /* sort runs ascending on (y,xs) */
                    810:        qsort(ra,no_runs,sizeof(RLE_Yrun),local_rn_asc);
                    811:        /* count RLE_lines.mny */
                    812:        rls.mny = 0; cy=INT_MIN;
                    813:        for(ri=0,cr=ra; ri<no_runs; ri++,cr++)
                    814:                if(cr->y!=cy) {
                    815:                        rls.mny++;
                    816:                        cy = cr->y;
                    817:                        };
                    818:        /* allocate RLE_lines */
                    819:        if((rls.rla=(RLE_Line *)malloc(rls.mny*sizeof(RLE_Line)))==NULL)
                    820:                abort("rle_lines_of_page: can't malloc rls.rla[%d]",rls.mny);
                    821:        /* fill in RLE_lines */
                    822:        cy=INT_MIN;  cl=rls.rla-1;
                    823:        for(ri=0,cr=ra; ri<no_runs; ri++,cr++) {
                    824:                if(cr->y!=cy) {
                    825:                        cl++;
                    826:                        cl->y = cy = cr->y;
                    827:                        cl->runs = 0;
                    828:                        lr = cl->r;
                    829:                        };
                    830:                lr->xs = cr->xs;  lr->xe = cr->xe;  lr++;  cl->runs++;
                    831:                };
                    832:        free(ra);
                    833:        return(&rls);
                    834:        }
                    835: 
                    836: Bbx *bbx_of_rle_lines(rlsp)
                    837:     RLE_Lines *rlsp;
                    838: {   static Bbx res;
                    839:     Bbx r;
                    840:     int li,ri;
                    841:     RLE_Line *lp;
                    842:     RLE_Run *rp;
                    843:        res = empty_Bbx;
                    844:        for(li=0,lp=rlsp->rla; li<rlsp->mny; li++,lp++) {
                    845:                r.a.y = r.b.y = lp->y;
                    846:                for(ri=0,rp=lp->r; ri<lp->runs; ri++,rp++) {
                    847:                        r.a.x = rp->xs;
                    848:                        r.b.x = rp->xe;
                    849:                        merge_bbx(&r,&res);
                    850:                        };
                    851:                };
                    852:        return(&res);
                    853:        }
                    854: 
                    855: translate_rle_lines(r,p)
                    856:     RLE_Lines *r;
                    857:     Sp p;
                    858: {   int li,ri;
                    859:     RLE_Line *lp;
                    860:     RLE_Run *rp;
                    861:        for(li=0,lp=r->rla; li<r->mny; li++,lp++) {
                    862:                lp->y += p.y;
                    863:                for(ri=0,rp=lp->r; ri<lp->runs; ri++,rp++) {
                    864:                        rp->xs += p.x;
                    865:                        rp->xe += p.x;
                    866:                        };
                    867:                };
                    868:        }
                    869: 
                    870: RLE_Line *binary_source(a)
                    871:     Copy_arg *a;
                    872: {   static RLE_Line rl;
                    873:     unsigned char *inline;
                    874:        a->bop = F;
                    875:        if(PIC_rline(a->ph,&inline)==1) {
                    876:                rl.runs =
                    877:                    rlbr(inline,0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->bx.a.x,rl.r);
                    878:                rl.y = a->ph->cy;
                    879:                rl.len = a->wid;
                    880:                if(_O.dbg_r) nerr_RLE_Line("binary_source: ",&rl);
                    881:                return(&rl);
                    882:                }
                    883:        else {  if(_O.dbg_r) nerr_RLE_Line("binary_source: ",NULL);
                    884:                return(NULL);
                    885:                };
                    886:        }
                    887: 
                    888: RLE_Line *bitmap_source(a)
                    889:     Copy_arg *a;
                    890: {   static RLE_Line rl;
                    891:     unsigned char *inline;
                    892:     register unsigned char *cp,*ep,*rb;
                    893:        a->bop = F;
                    894:        if(PIC_rline(a->ph,&inline)==1) {
                    895:                /* reverse bit order in each byte */
                    896:                rb=bm_consts.Rbits;
                    897:                ep=(cp=inline)+a->ph->bpl;
                    898:                while(cp<ep) { *cp = rb[*cp]; cp++; };
                    899:                rl.runs =
                    900:                    rlbr(inline,0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->bx.a.x,rl.r);
                    901:                rl.y = a->ph->cy;
                    902:                rl.len = a->wid;
                    903:                if(_O.dbg_r) nerr_RLE_Line("bitmap_source: ",&rl);
                    904:                return(&rl);
                    905:                }
                    906:        else {  if(_O.dbg_r) nerr_RLE_Line("binary_source: ",NULL);
                    907:                return(NULL);
                    908:                };
                    909:        }
                    910: 
                    911: RLE_Line *bitfile_source(a)
                    912:     Copy_arg *a;
                    913: #define dbg_Bi (F)
                    914: {   static RLE_Line rl;
                    915:     unsigned char *cp,*ep,*pp;
                    916:     int ch,ci;
                    917:        a->bop = F;
                    918:        /* copy current line to prior */
                    919:        memcpy(a->ph->pline,a->ph->line,a->ph->bpl);
                    920:        /* read one binary raster line */
                    921:        ep=(cp=a->ph->line)+a->ph->bpl;
                    922:        while(cp<ep) {
                    923:                if((ch=getc(a->ph->fp))!=EOF) {
                    924:                        if(ch<127) {
                    925:                                if(dbg_Bi) err("cb: %o",ch);
                    926:                                if((fread(cp,1,2*ch,a->ph->fp))==2*ch) {
                    927:                                        cp += 2*ch;
                    928:                                        }
                    929:                                else return(NULL);
                    930:                                }
                    931:                        else {  ch &= 0x7F;
                    932:                                if(dbg_Bi) err("cb: 0200+%o",ch);
                    933:                                if((fread(cp,1,2,a->ph->fp))==2) {
                    934:                                        cp += 2;
                    935:                                        for(ci=0;ci<ch-1;ci++,cp+=2) {
                    936:                                                *cp = *(cp-2);
                    937:                                                *(cp+1) = *(cp-1);
                    938:                                                };
                    939:                                        }
                    940:                                else return(NULL);
                    941:                                };
                    942:                        }
                    943:                else return(NULL);
                    944:                };
                    945:        /* reverse bit-order, & xor with prior line */
                    946:        for(ep=(cp=a->ph->line)+a->ph->bpl,pp=a->ph->pline; cp<ep; cp++,pp++) {
                    947:                *cp = bm_consts.Rbits[*cp] ^ *pp;
                    948:                if(dbg_Bi) err("db: %o = ?? ^ %o",*cp,*pp);
                    949:                };
                    950:        rl.runs =
                    951:            rlbr(a->ph->line,0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->bx.a.x,rl.r);
                    952:        rl.y = ++a->ph->cy;
                    953:        rl.len = a->wid;
                    954:        if(_O.dbg_r) nerr_RLE_Line("bitfile_source: ",&rl);
                    955:        return(&rl);
                    956:        }
                    957: 
                    958: RLE_Line *dim_source(a)
                    959:     Copy_arg *a;
                    960: {   static RLE_Line *rlp,*rlq,rl;
                    961:        if(a->bop) {
                    962:                a->ph->cy = a->ph->bx.a.y-1;
                    963:                rlq=(rlp=a->rles.rla)+a->rles.mny;
                    964:                };
                    965:        if(_O.dbg_r) {
                    966:                err("dim_source: a->bop %d a->ph->cy %d",a->bop,a->ph->cy);
                    967:                nerr_RLE_Line("*rlp",rlp);
                    968:                };
                    969:        a->bop = F;
                    970:        a->ph->cy++;
                    971:        if(rlp<rlq) {
                    972:                if(a->ph->cy < rlp->y) {
                    973:                        rl.y = a->ph->cy;
                    974:                        rl.runs = 0;
                    975:                        rl.len = a->wid;
                    976:                        if(_O.dbg_r) nerr_RLE_Line("dim_source: ",&rl);
                    977:                        return(&rl);
                    978:                        }
                    979:                else if(a->ph->cy == rlp->y) {
                    980:                        rlp->len = a->wid;
                    981:                        rlp++;
                    982:                        if(_O.dbg_r) nerr_RLE_Line("dim_source: ",rlp-1);
                    983:                        return(rlp-1);
                    984:                        }
                    985:                else {  while(rlp<rlq && a->ph->cy>rlp->y) rlp++;
                    986:                        if(rlp>=rlq) {
                    987:                                if(_O.dbg_r) nerr_RLE_Line("dim_source: NULL");
                    988:                                return(NULL);
                    989:                                }
                    990:                        else {  rlp->len = a->wid;
                    991:                                rlp++;
                    992:                                if(_O.dbg_r) nerr_RLE_Line("dim_source: ",rlp-1);
                    993:                                return(rlp-1);
                    994:                                };
                    995:                        };
                    996:                }
                    997:        else {  if(_O.dbg_r) nerr_RLE_Line("dim_source: NULL");
                    998:                return(NULL);
                    999:                };
                   1000:        }
                   1001: 
                   1002: RLE_Line *rle_source(a)
                   1003:     Copy_arg *a;
                   1004: {   static RLE_Line *rl;
                   1005:        a->bop = F;
                   1006:        if((rl=RLE_get_Line(a->ph->bx.a.x,a->ph->bx.b.x))!=NULL) {
                   1007:                a->ph->cy = rl->y;
                   1008:                rl->len = a->wid;
                   1009:                if(_O.dbg_r) nerr_RLE_Line("rle_source: ",rl);
                   1010:                return(rl);
                   1011:                }
                   1012:        else {  if(_O.dbg_r) nerr_RLE_Line("rle_source: ",NULL);
                   1013:                return(NULL);
                   1014:                };
                   1015:        }
                   1016: 
                   1017: /* Read next line of runs from pic file, with runs shifted to lie in the range
                   1018:    [ a->ph->bx.a.x, a->ph->bx.b.x ]. */
                   1019: RLE_Line *pic_source(a)
                   1020:     Copy_arg *a;
                   1021: {   static RLE_Line rl;
                   1022:     unsigned char *inline;
                   1023:        a->bop = F;
                   1024:        if(PIC_rline(a->ph,&inline)==1) {
                   1025:                rl.runs = trcr(inline,
                   1026:                        0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->bx.a.x,
                   1027:                        a->thresh,rl.r);
                   1028:                rl.y = a->ph->cy;
                   1029:                rl.len = a->wid;
                   1030:                if(_O.dbg_r) nerr_RLE_Line("pic_source: ",&rl);
                   1031:                return(&rl);
                   1032:                }
                   1033:        else {  if(_O.dbg_r) nerr_RLE_Line("pic_source: ",NULL);
                   1034:                return(NULL);
                   1035:                };
                   1036:        }
                   1037: 
                   1038: /* Read next line of runs from g31 file, with runs shifted to lie in the range
                   1039:    [ a->ph->bx.a.x, a->ph->bx.b.x ]. */
                   1040: RLE_Line *g31_source(a)
                   1041:     Copy_arg *a;
                   1042: {   static RLE_Line *rlp,rl;
                   1043:     RLE_Run *rp,*ep,*np;
                   1044:        if((rlp=g31_to_rlel(a->tbl,a->bf,a->bop))!=NULL) {
                   1045:                a->bop = F;
                   1046:                rlp->y = ++a->ph->cy;
                   1047:                rlp->len = a->wid;
                   1048:                if(a->ph->bx.a.x!=0) {
                   1049:                        /* must shift run indices */
                   1050:                        rl.y = rlp->y;
                   1051:                        rl.len = rlp->len;
                   1052:                        if((rl.runs=rlp->runs)>0) {
                   1053:                                for(ep=(rp=rlp->r)+rlp->runs,np=rl.r; rp<ep; rp++,np++ ) {
                   1054:                                        np->xs = rp->xs + a->ph->bx.a.x;
                   1055:                                        np->xe = rp->xe + a->ph->bx.a.x;
                   1056:                                        };
                   1057:                                };
                   1058:                        if(_O.dbg_r) nerr_RLE_Line("g31_source: ",&rl);
                   1059:                        return(&rl);
                   1060:                        }
                   1061:                else {  if(_O.dbg_r) nerr_RLE_Line("g31_source: ",rlp);
                   1062:                        return(rlp);
                   1063:                        };
                   1064:                }
                   1065:        else {  if(_O.dbg_r) nerr_RLE_Line("g31_source: ",NULL);
                   1066:                return(NULL);
                   1067:                };
                   1068:        }
                   1069: 
                   1070: /* Read next line of runs from g32 file, with runs shifted to lie in the range
                   1071:    [ a->ph->bx.a.x, a->ph->bx.b.x ]. */
                   1072: RLE_Line *g32_source(a)
                   1073:     Copy_arg *a;
                   1074: {   static RLE_Line *rlp,rl;
                   1075:     RLE_Run *rp,*ep,*np;
                   1076:        if((rlp=g32_to_rlel(a->tbl,a->bf,a->bop))!=NULL) {
                   1077:                a->bop = F;
                   1078:                rlp->y = ++a->ph->cy;
                   1079:                rlp->len = a->wid;
                   1080:                if(a->ph->bx.a.x!=0) {
                   1081:                        /* must shift run indices */
                   1082:                        if(_O.dbg_r) err("g32_source: shift +%d",a->ph->bx.a.x);
                   1083:                        rl.y = rlp->y;
                   1084:                        rl.len = rlp->len;
                   1085:                        if((rl.runs=rlp->runs)>0) {
                   1086:                                for(ep=(rp=rlp->r)+rlp->runs,np=rl.r; rp<ep; rp++,np++ ) {
                   1087:                                        np->xs = rp->xs + a->ph->bx.a.x;
                   1088:                                        np->xe = rp->xe + a->ph->bx.a.x;
                   1089:                                        };
                   1090:                                };
                   1091:                        if(_O.dbg_r) nerr_RLE_Line("g32_source: ",&rl);
                   1092:                        return(&rl);
                   1093:                        }
                   1094:                else {  if(_O.dbg_r) nerr_RLE_Line("g32_source: ",rlp);
                   1095:                        return(rlp);
                   1096:                        };
                   1097:                }
                   1098:        else {  if(_O.dbg_r) nerr_RLE_Line("g32_source: ",NULL);
                   1099:                return(NULL);
                   1100:                };
                   1101:        }
                   1102: 
                   1103: /* Read next line of runs from g4 file, after shifting runs to lie in the range
                   1104:    [ a->ph->bx.a.x, a->ph->bx.b.x ]. */
                   1105: RLE_Line *g4_source(a)
                   1106:     Copy_arg *a;
                   1107: {   static RLE_Line *rlp,rl;
                   1108:     RLE_Run *rp,*ep,*np;
                   1109:        if((rlp=g4_to_rlel(a->tbl,a->bf,a->bop,a->wid))!=NULL) {
                   1110:                a->bop = F;
                   1111:                rlp->y = ++a->ph->cy;
                   1112:                rlp->len = a->wid;
                   1113:                if(a->ph->bx.a.x!=0) { /* shift runs */
                   1114:                        rl.y = rlp->y;
                   1115:                        rl.len = rlp->len;
                   1116:                        if((rl.runs=rlp->runs)>0) {
                   1117:                                for(ep=(rp=rlp->r)+rlp->runs,np=rl.r; rp<ep; rp++,np++ ) {
                   1118:                                        np->xs = rp->xs + a->ph->bx.a.x;
                   1119:                                        np->xe = rp->xe + a->ph->bx.a.x;
                   1120:                                        };
                   1121:                                };
                   1122:                        if(_O.dbg_r) nerr_RLE_Line("g4_source: ",&rl);
                   1123:                        return(&rl);
                   1124:                        }
                   1125:                else {  if(_O.dbg_r) nerr_RLE_Line("g4_source: ",rlp);
                   1126:                        return(rlp);
                   1127:                        };
                   1128:                }
                   1129:        else {  a->bop = F;
                   1130:                if(_O.dbg_r) nerr_RLE_Line("g4_source: ",NULL);
                   1131:                return(NULL);
                   1132:                };
                   1133:        }
                   1134: 
                   1135: binary_sink(rl,a)
                   1136:     RLE_Line *rl;
                   1137:     Copy_arg *a;
                   1138: {   int stat;
                   1139:        if(_O.dbg_r) nerr_RLE_Line("binary_sink: ",rl);
                   1140:        if(a->bop) { PIC_put_hdr(a->ph); a->bop=F; }
                   1141:        if(rl!=NULL) {
                   1142:                memset(a->ph->line,'\0',a->ph->bpl);
                   1143:                if(rl->runs>0) {
                   1144:                    /* convert *rl to binary, using ``little-endian'' bit-order */
                   1145:                    brrl(rl->runs,rl->r,a->ph->bx.a.x,a->ph->bx.b.x,0,a->ph->line);
                   1146:                    };
                   1147:                if((stat=PIC_wline(a->ph,a->ph->line))!=1)
                   1148:                        abort("binary_sink: can't write: stat %d",stat);
                   1149:                };
                   1150:        return(1);
                   1151:        }
                   1152: 
                   1153: bitmap_sink(rl,a)
                   1154:     RLE_Line *rl;
                   1155:     Copy_arg *a;
                   1156: {   int stat;
                   1157:        if(_O.dbg_r) nerr_RLE_Line("bitmap_sink: ",rl);
                   1158:        if(a->bop) { PIC_put_hdr(a->ph); a->bop=F; }
                   1159:        if(rl!=NULL) {
                   1160:                memset(a->ph->line,'\0',a->ph->bpl);
                   1161:                if(rl->runs>0) {
                   1162:                    /* convert *rl to binary, using ``big-endian'' bit-order */
                   1163:                    brrlb(rl->runs,rl->r,a->ph->bx.a.x,a->ph->bx.b.x,0,a->ph->line);
                   1164:                    };
                   1165:                if((stat=PIC_wline(a->ph,a->ph->line))!=1)
                   1166:                        abort("bitmap_sink: can't write: stat %d",stat);
                   1167:                };
                   1168:        return(1);
                   1169:        }
                   1170: 
                   1171: /* Write bitfile(9.5) format */
                   1172: bitfile_sink(rl,a)
                   1173:     RLE_Line *rl;
                   1174:     Copy_arg *a;
                   1175: #define dbg_Bo (F)
                   1176: {   int stat;
                   1177:     int ci,towrite;
                   1178:     register unsigned char uc,*cp,*pp,*ep;
                   1179:        if(_O.dbg_r||dbg_Bo) nerr_RLE_Line("bitfile_sink: ",rl);
                   1180:        if(a->bop) { PIC_put_hdr(a->ph); a->bop=F; }
                   1181:        if(rl!=NULL) {
                   1182:                /* copy current to prior */
                   1183:                memcpy(a->ph->pline,a->ph->line,a->ph->bpl);
                   1184:                memset(a->ph->line,'\0',a->ph->bpl);
                   1185:                if(rl->runs>0) {
                   1186:                        /* convert *rl to binary, using ``big-endian'' bit-order */
                   1187:                        brrlb(rl->runs,rl->r,
                   1188:                                a->ph->bx.a.x,a->ph->bx.b.x,
                   1189:                                0,a->ph->line);
                   1190:                        if(dbg_Bo) {
                   1191:                            unsigned char *cb,*eb;
                   1192:                                fprintf(stderr,"a->ph->line: ");
                   1193:                                for(eb=(cb=a->ph->line)+a->ph->bpl;cb<eb;cb++)
                   1194:                                        fprintf(stderr,"%02X",*cb);
                   1195:                                fprintf(stderr,"\n");
                   1196:                                };
                   1197:                        };
                   1198:                /* break up output into blocks of 2*126 bytes;
                   1199:                   SHOULD also try run-length coding */
                   1200:                ci=0;  while((towrite=a->ph->bpl-ci) > 0) {
                   1201:                        if(towrite >= 2*127) towrite=2*126;
                   1202:                        /* write control byte for block */
                   1203:                        uc = towrite/2;
                   1204:                        if(dbg_Bo) err("cb: %02X",uc);
                   1205:                        putc(uc,a->ph->fp);
                   1206:                        for(ep=(cp=a->ph->line+ci)+towrite,pp=a->ph->pline+ci;
                   1207:                             cp<ep; cp++,pp++) {
                   1208:                                /* write XOR byte */
                   1209:                                uc = *cp ^ *pp;
                   1210:                                if(dbg_Bo) err("db %d: %02X = c%02X ^ p%02X",cp-a->ph->line,uc,*cp,*pp);
                   1211:                                putc(uc,a->ph->fp);
                   1212:                                };
                   1213:                        ci += towrite;
                   1214:                        };
                   1215:                }
                   1216:        else {  free(a->ph->line);  a->ph->line=NULL;
                   1217:                free(a->ph->pline);  a->ph->pline=NULL;
                   1218:                fflush(a->ph->fp);
                   1219:                };
                   1220:        }
                   1221: 
                   1222: rle_sink(rl,a)
                   1223:     RLE_Line *rl;
                   1224:     Copy_arg *a;
                   1225: {      if(_O.dbg_r) nerr_RLE_Line("rle_sink: ",rl);
                   1226:        if(a->bop) {
                   1227:            RIC_hdr rh;
                   1228:                rh.bx = a->ph->bx;
                   1229:                rh.res_x = a->ph->res_x;
                   1230:                rh.res_y = a->ph->res_y;
                   1231:                RLE_put_hdr(fileno(a->ph->fp),&rh,1);
                   1232:                a->ph->cy = a->ph->bx.a.y-1;
                   1233:                a->bop=F;
                   1234:                };
                   1235:        if(rl!=NULL) {
                   1236:                if(rl->runs>0) RLE_put_Line(fileno(a->ph->fp),rl);
                   1237:                a->ph->cy++;
                   1238:                }
                   1239:        else RLE_close(fileno(a->ph->fp));
                   1240:        return(1);
                   1241:        }
                   1242: 
                   1243: /* Write next line of runs to g31 file, after shifting runs to lie in the range
                   1244:    [ 0, a->ph->bx.b.x - a->ph->bx.a.x ]. */
                   1245: g31_sink(rl,a)
                   1246:     RLE_Line *rl;
                   1247:     Copy_arg *a;
                   1248: {   int stat;
                   1249:     RLE_Line crl;
                   1250:     RLE_Run *rp,*ep,*np;
                   1251:        if(_O.dbg_r) nerr_RLE_Line("g31_sink: ",rl);
                   1252:        if(a->bop) {
                   1253:                PIC_put_hdr(a->ph);
                   1254:                /* treat FILE *a->ph->fp as a sequence of bits */
                   1255:                if((a->bf=bopen(a->ph->fp,"w"))==NULL)
                   1256:                        abort("g31_sink: can't open bitfile");
                   1257:                BOF_to_g31(a->bf);
                   1258:                a->bop=F;
                   1259:                };
                   1260:        if(rl!=NULL) {
                   1261:                /* check that rl->len is consistent with a->ph */
                   1262:                if(rl->len != a->ph->bx.b.x - a->ph->bx.a.x + 1) {
                   1263:                        err("g31_sink: rl->len %d != wid(a->ph.bx) %d",
                   1264:                                rl->len, a->ph->bx.b.x - a->ph->bx.a.x + 1);
                   1265:                        rl->len = a->ph->bx.b.x - a->ph->bx.a.x + 1;
                   1266:                        };
                   1267:                if(rl->runs>0) {
                   1268:                        if(a->ph->bx.a.x!=0) { /* shift runs */
                   1269:                                crl.y = rl->y;
                   1270:                                crl.len = rl->len;
                   1271:                                crl.runs = rl->runs;
                   1272:                                for(ep=(rp=rl->r)+rl->runs,np=crl.r;
                   1273:                                     rp<ep;
                   1274:                                      rp++,np++) {
                   1275:                                        np->xs = rp->xs - a->ph->bx.a.x;
                   1276:                                        np->xe = rp->xe - a->ph->bx.a.x;
                   1277:                                        };
                   1278:                                rlel_to_g31(&crl,crl.len,a->bf);
                   1279:                                }
                   1280:                        else rlel_to_g31(rl,rl->len,a->bf);
                   1281:                        }
                   1282:                else rlel_to_g31(NULL,rl->len,a->bf);
                   1283:                a->ph->cy++;
                   1284:                }
                   1285:        else {  EOF_to_g31(a->bf);
                   1286:                bclose(a->bf);
                   1287:                };
                   1288:        return(1);
                   1289:        }
                   1290: 
                   1291: /* Write next line of runs to g32 file, after shifting runs to lie in the range
                   1292:    [ 0, a->ph->bx.b.x - a->ph->bx.a.x ]. */
                   1293: g32_sink(rl,a)
                   1294:     RLE_Line *rl;
                   1295:     Copy_arg *a;
                   1296: {   static RLE_Line prl;
                   1297:     RLE_Line *pl;
                   1298:     RLE_Line crl;
                   1299:     RLE_Run *rp,*ep,*np;
                   1300:        if(_O.dbg_r) nerr_RLE_Line("g32_sink: ",rl);
                   1301:        if(a->bop) {
                   1302:                PIC_put_hdr(a->ph);
                   1303:                /* treat FILE *a->ph->fp as a sequence of bits */
                   1304:                if((a->bf=bopen(a->ph->fp,"w"))==NULL)
                   1305:                        abort("can't open bitfile");
                   1306:                BOF_to_g32(a->bf);
                   1307:                a->bop=F;
                   1308:                prl.runs = 0;
                   1309:                };
                   1310:        if(rl!=NULL) {
                   1311:                /* check that rl->len is consistent with a->ph */
                   1312:                if(rl->len != a->ph->bx.b.x - a->ph->bx.a.x + 1) {
                   1313:                        err("g32_sink: rl->len %d != wid(a->ph.bx) %d",
                   1314:                                rl->len, a->ph->bx.b.x - a->ph->bx.a.x + 1);
                   1315:                        rl->len = a->ph->bx.b.x - a->ph->bx.a.x + 1;
                   1316:                        };
                   1317:                prl.len = rl->len;
                   1318:                prl.y = rl->y - 1;
                   1319:                if(((a->ph->cy+1-a->ph->bx.a.y)%a->k)==0) pl=NULL; else pl=&prl;
                   1320:                if(rl->runs>0) {
                   1321:                        if(a->ph->bx.a.x!=0) { /* shift runs */
                   1322:                                crl.y = rl->y;
                   1323:                                crl.len = rl->len;
                   1324:                                crl.runs = rl->runs;
                   1325:                                for(ep=(rp=rl->r)+rl->runs,np=crl.r;
                   1326:                                     rp<ep;
                   1327:                                      rp++,np++) {
                   1328:                                        np->xs = rp->xs - a->ph->bx.a.x;
                   1329:                                        np->xe = rp->xe - a->ph->bx.a.x;
                   1330:                                        };
                   1331:                                rlel_to_g32(pl,&crl,crl.len,a->bf);
                   1332:                                prl.y=crl.y;
                   1333:                                prl.len=crl.len;
                   1334:                                prl.runs=crl.runs;
                   1335:                                memcpy(prl.r,crl.r,2*prl.runs*sizeof(short));
                   1336:                                }
                   1337:                        else {  rlel_to_g32(pl,rl,rl->len,a->bf);
                   1338:                                prl.y=rl->y;
                   1339:                                prl.len=rl->len;
                   1340:                                prl.runs=rl->runs;
                   1341:                                memcpy(prl.r,rl->r,2*prl.runs*sizeof(short));
                   1342:                                };
                   1343:                        }
                   1344:                else {  rlel_to_g32(pl,NULL,rl->len,a->bf);
                   1345:                        prl.y=rl->y;
                   1346:                        prl.len=rl->len;
                   1347:                        prl.runs=0;
                   1348:                        }
                   1349:                a->ph->cy++;
                   1350:                }
                   1351:        else {  EOF_to_g32(a->bf);
                   1352:                bclose(a->bf);
                   1353:                prl.runs = 0;
                   1354:                };
                   1355:        return(1);
                   1356:        }
                   1357: 
                   1358: /* Write next line of runs to g4 file, after shifting runs to lie in the range
                   1359:    [ 0, a->ph->bx.b.x - a->ph->bx.a.x ]. */
                   1360: g4_sink(rl,a)
                   1361:     RLE_Line *rl;
                   1362:     Copy_arg *a;
                   1363: {   static RLE_Line prl;
                   1364:     RLE_Line crl;
                   1365:     RLE_Run *rp,*ep,*np;
                   1366:        if(_O.dbg_r) nerr_RLE_Line("g4_sink: ",rl);
                   1367:        if(a->bop) {
                   1368:                PIC_put_hdr(a->ph);
                   1369:                /* treat FILE *a->ph->fp as a sequence of bits */
                   1370:                if((a->bf=bopen(a->ph->fp,"w"))==NULL)
                   1371:                        abort("can't open bitfile");
                   1372:                BOF_to_g4(a->bf);
                   1373:                a->bop=F;
                   1374:                prl.runs = 0;
                   1375:                };
                   1376:        if(rl!=NULL) {
                   1377:                /* check that rl->len is consistent with a->ph */
                   1378:                if(rl->len != a->ph->bx.b.x - a->ph->bx.a.x + 1) {
                   1379:                        err("g4_sink: rl->len %d != wid(a->ph.bx) %d",
                   1380:                                rl->len, a->ph->bx.b.x - a->ph->bx.a.x + 1);
                   1381:                        rl->len = a->ph->bx.b.x - a->ph->bx.a.x + 1;
                   1382:                        };
                   1383:                if(rl->runs>0) {
                   1384:                        if(a->ph->bx.a.x!=0) { /* shift runs */
                   1385:                                crl.y = rl->y;
                   1386:                                crl.len = rl->len;
                   1387:                                crl.runs = rl->runs;
                   1388:                                for(ep=(rp=rl->r)+rl->runs,np=crl.r;
                   1389:                                     rp<ep;
                   1390:                                      rp++,np++) {
                   1391:                                        np->xs = rp->xs - a->ph->bx.a.x;
                   1392:                                        np->xe = rp->xe - a->ph->bx.a.x;
                   1393:                                        };
                   1394:                                rlel_to_g4(&prl,&crl,crl.len,a->bf);
                   1395:                                prl.y=crl.y;
                   1396:                                prl.len=crl.len;
                   1397:                                prl.runs=crl.runs;
                   1398:                                memcpy(prl.r,crl.r,2*prl.runs*sizeof(short));
                   1399:                                }
                   1400:                        else {  rlel_to_g4(&prl,rl,rl->len,a->bf);
                   1401:                                prl.y=rl->y;
                   1402:                                prl.len=rl->len;
                   1403:                                prl.runs=rl->runs;
                   1404:                                memcpy(prl.r,rl->r,2*prl.runs*sizeof(short));
                   1405:                                };
                   1406:                        }
                   1407:                else {  rlel_to_g4(&prl,NULL,rl->len,a->bf);
                   1408:                        prl.runs=0;
                   1409:                        }
                   1410:                a->ph->cy++;
                   1411:                }
                   1412:        else {  EOF_to_g4(a->bf);
                   1413:                bclose(a->bf);
                   1414:                prl.runs = 0;
                   1415:                };
                   1416:        return(1);
                   1417:        }
                   1418: 
                   1419: pic_sink(rl,a)
                   1420:     RLE_Line *rl;
                   1421:     Copy_arg *a;
                   1422: {   int stat;
                   1423:        if(_O.dbg_r) nerr_RLE_Line("pic_sink: ",rl);
                   1424:        if(a->bop) {
                   1425:                PIC_put_hdr(a->ph);
                   1426:                a->bop=F;
                   1427:                };
                   1428:        if(rl!=NULL) {
                   1429:                crrl(rl->runs,rl->r,0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->line);
                   1430:                if((stat=PIC_wline(a->ph,a->ph->line))!=1)
                   1431:                        abort("pic_sink: can't write: stat %d",stat);
                   1432:                };
                   1433:        return(1);
                   1434:        }
                   1435: 
                   1436: #if CPU==SUN
                   1437: post_sink(rl,a)
                   1438:     RLE_Line *rl;
                   1439:     Copy_arg *a;
                   1440: {   int stat;
                   1441:        if(_O.dbg_r) nerr_RLE_Line("post_sink: ",rl);
                   1442:        if (a->bop) {
                   1443:                PIC_put_hdr(a->ph);     /* needed for allocation of h->line? */
                   1444:                POST_start(a->ph);
                   1445:                a->bop = F;
                   1446:                };
                   1447:        if(rl!=NULL) {
                   1448:                memset(a->ph->line,'\0',a->ph->bpl);
                   1449:                if(rl->runs>0) {
                   1450:                    /* convert *rl to binary, using ``little-endian'' bit-order */
                   1451:                    brrl(rl->runs,rl->r,a->ph->bx.a.x,a->ph->bx.b.x,0,a->ph->line);
                   1452:                    };
                   1453:                if((stat=POST_wline(a->ph,a->ph->line))!=1)
                   1454:                        abort("post_sink: can't write: stat %d",stat);
                   1455:                }
                   1456:        else {  POST_end();
                   1457:                };
                   1458:        return(1);
                   1459:        }
                   1460: #else
                   1461: post_sink() {abort("-P postscript output unimplemented");};
                   1462: #endif
                   1463: 
                   1464: #if CPU==SUN
                   1465: rast_sink(rl,a)
                   1466:     RLE_Line *rl;
                   1467:     Copy_arg *a;
                   1468: {   int stat;
                   1469:        if(_O.dbg_r) nerr_RLE_Line("rast_sink: ",rl);
                   1470:        if (a->bop) {
                   1471:                PIC_put_hdr(a->ph);     /* needed for allocation of h->line? */
                   1472:                RAST_start(a->ph);
                   1473:                a->bop = F;
                   1474:                };
                   1475:        if(rl!=NULL) {
                   1476:                memset(a->ph->line,'\0',a->ph->bpl);
                   1477:                if(rl->runs>0) {
                   1478:                    /* convert *rl to binary, using ``little-endian'' bit-order */
                   1479:                    brrl(rl->runs,rl->r,a->ph->bx.a.x,a->ph->bx.b.x,0,a->ph->line);
                   1480:                    };
                   1481:                if((stat=RAST_wline(a->ph,a->ph->line))!=1)
                   1482:                        abort("rast_sink: can't write: stat %d",stat);
                   1483:                }
                   1484:        else {  RAST_end();
                   1485:                };
                   1486:        return(1);
                   1487:        }
                   1488: #else
                   1489: rast_sink() {abort("-S sunraster output unimplemented");};
                   1490: #endif
                   1491: 
                   1492: /* Save RLE_Line *rl in buffer, as packed binary, using ``little-endian''
                   1493:    bit-packing order, rounding each line to the nearest int for speed.
                   1494:    If a->bop, malloc a complete, contiguous buffer holding the entire page,
                   1495:    and initialize its contents to zeroes.
                   1496:    On each call with rl!=NULL, convert the given line to binary & save in buffer.
                   1497:    When called with rl==NULL but a!=NULL, signalling end-of-page, do nothing.
                   1498:    Normally, return kludgey (unsigned int *)1, like other sink functions.
                   1499:    When called with rl==NULL && a==NULL, return pointer to buffer.
                   1500:    It is the responsibility of the calling code to free the buffer. */
                   1501: unsigned int *binary_buffer(rl,a)
                   1502:     RLE_Line *rl;
                   1503:     Copy_arg *a;
                   1504: {   static unsigned int *buf = NULL;
                   1505:     static int ipl = 0;        /* ints/line */
                   1506:     int bufsz;         /* (bytes) */
                   1507:     unsigned int *result;
                   1508: #define BITS_PER_INT (8*sizeof(int))
                   1509:        if(a!=NULL && a->bop) {
                   1510:                /* round up to int boundary */
                   1511:                ipl = (bbx_wid(&(a->ph->bx))+BITS_PER_INT-1)/BITS_PER_INT;
                   1512:                bufsz = sizeof(int)*ipl*bbx_hgt(&(a->ph->bx));
                   1513:                if((buf=(unsigned int *)malloc(bufsz))==NULL)
                   1514:                        abort("binary_buffer: can't alloc int buf[%d]",bufsz/sizeof(int));
                   1515:                memset(buf,'\0',bufsz);
                   1516:                a->bop=F;
                   1517:                };
                   1518:        if(rl!=NULL) {
                   1519:                /* convert *rl to binary, using ``little-endian'' bit-order */
                   1520:                if(rl->runs>0) {
                   1521:                        /* *rl --> binary, with ``little-endian'' bit-order */
                   1522: #if BIG_ENDIAN
                   1523:                        brrlb( rl->runs, rl->r, a->ph->bx.a.x, a->ph->bx.b.x,
                   1524:                                0, buf+(ipl*(rl->y-a->ph->bx.a.y)) );
                   1525: #else
                   1526:                        brrl( rl->runs, rl->r, a->ph->bx.a.x, a->ph->bx.b.x,
                   1527:                                0, buf+(ipl*(rl->y-a->ph->bx.a.y)) );
                   1528: #endif
                   1529:                        };
                   1530:                return((unsigned int *)1);
                   1531:                }
                   1532:        else {  if(a!=NULL) return((unsigned int *)1);
                   1533:                else {  result = buf;
                   1534:                        buf = NULL;  ipl = 0;
                   1535:                        return(result);
                   1536:                        };
                   1537:                };
                   1538:        }
                   1539: 
                   1540: /* Rotate binary buffer *buf (whose shape is specified by a->ph->bx),
                   1541:    through angle tra->rot, and write the resulting stream of RLE_Line's to
                   1542:    sink() one at a time, along with a rotated version of *a as the 2nd argument.
                   1543:    Only PI/2 is supported; UNDER DEVELOPMENT:  other multiples of PI/2 and
                   1544:    small arbitrary angles. */
                   1545: rotate_binary_buffer(buf,tra,sink,a)
                   1546:     unsigned int *buf;
                   1547:     Transform_rlel_arg *tra;
                   1548:     int (*sink)();     /* takes args:  (RLE_Line *), and int */
                   1549:     Copy_arg *a;
                   1550: {   register int ipl;          /* ints/line in binary buffer */
                   1551:     Copy_arg ra;               /* rotated */
                   1552:     RLE_Line rl;
                   1553: #define TINY_ANG (PI/1000)
                   1554:        /* round up to int boundary */
                   1555:        ipl = (bbx_wid(&(a->ph->bx))+BITS_PER_INT-1)/BITS_PER_INT;
                   1556:        ra = *a;
                   1557:        ra.bop=T;
                   1558:        if((ra.ph = (PIC_hdr *)malloc(sizeof(PIC_hdr)))==NULL)
                   1559:                abort("rotate_binary_buffer: can't malloc ra.ph");
                   1560:        *(ra.ph) = *(a->ph);
                   1561:        /* by arbitrary convention, rotated bx.a will coincide with input bx.a */
                   1562:        if(tra->rot <= PI/2+TINY_ANG && tra->rot >= PI/2-TINY_ANG) {
                   1563:            int ey,ii;
                   1564:            register RLE_Run *rp;
                   1565:            register unsigned int *cb,*eb,bm,obm;
                   1566:            register short rx;
                   1567:                ra.ph->bx.b.x = a->ph->bx.a.x + bbx_hgt(&(a->ph->bx)) - 1;
                   1568:                ra.ph->bx.b.y = a->ph->bx.a.y + bbx_wid(&(a->ph->bx)) - 1;
                   1569:                rl.len = ra.wid = bbx_wid(&(ra.ph->bx));
                   1570:                rl.y = ra.ph->bx.a.y;  ey=ra.ph->bx.b.y;
                   1571:                ii=0;  bm=01;
                   1572:                do {    obm=0;  /* assume 0 left of margin */
                   1573:                        rp=rl.r-1;
                   1574:                        rx=ra.ph->bx.a.x;
                   1575:                        cb=(eb=buf+ii)+((rl.len-1)*ipl);
                   1576:                        do {    if((*cb & bm)!=obm) {
                   1577:                                        if(obm) { rp->xe=rx-1;  obm=0; }
                   1578:                                        else { (++rp)->xs=rx;  obm=bm; };
                   1579:                                        };
                   1580:                                rx++;
                   1581:                                }
                   1582:                        while( (cb -= ipl) >= eb );
                   1583:                        if(obm) rp->xe=rx-1;
                   1584:                        rl.runs = rp - rl.r + 1;
                   1585:                        sink(&rl,&ra);
                   1586:                        if((bm<<=1)==0) {ii++; bm=01;};
                   1587:                        }
                   1588:                while((++rl.y)<=ey);
                   1589:                }
                   1590:        else if(tra->rot <= PI+TINY_ANG && tra->rot >= PI-TINY_ANG) {
                   1591:                rl.len = ra.wid;
                   1592:                abort("rotate_binary_buffer: tra->rot==%g deg unimplemented",
                   1593:                        tra->rot/DtoR);
                   1594:                }
                   1595:        else if(tra->rot <= 3*PI/2+TINY_ANG && tra->rot >= 3*PI/2-TINY_ANG) {
                   1596:                ra.ph->bx.b.x = a->ph->bx.a.x + bbx_hgt(&(a->ph->bx)) - 1;
                   1597:                ra.ph->bx.b.y = a->ph->bx.a.y + bbx_wid(&(a->ph->bx)) - 1;
                   1598:                rl.len = ra.wid = bbx_wid(&(ra.ph->bx));
                   1599:                abort("rotate_binary_buffer: tra->rot==%g deg unimplemented",
                   1600:                        tra->rot/DtoR);
                   1601:                }
                   1602:        else if(tra->rot <= 20.0*DtoR && tra->rot >= -20.0*DtoR) {
                   1603:            /* rotation by ``small'' angle */
                   1604:            Sp ce;              /* center of image to be rotated */
                   1605:            double rcos,rsin;   /* real rotation vector (cos,sin) */
                   1606:            double irx,iry;     /* current rotated pixel location */
                   1607:            register int sx,sy,ex,ey,rx,ry;
                   1608:            register RLE_Run *rp;
                   1609:            register int pel,opel;
                   1610:            register int orx,ory;
                   1611:                if(0) err("rotate_binary_buffer: tra->rot==%g deg under development",
                   1612:                        tra->rot/DtoR);
                   1613:                /* conventionally, keep the same window as the input image,
                   1614:                   while rotating about its midpoint */
                   1615:                rl.len = ra.wid = bbx_wid(&(ra.ph->bx));
                   1616:                sx = ra.ph->bx.a.x;  ex = ra.ph->bx.b.x;
                   1617:                sy = ra.ph->bx.a.y;  ey = ra.ph->bx.b.y;
                   1618:                ce.x = sx + bbx_wid(&(ra.ph->bx))/2;
                   1619:                ce.y = sy + bbx_hgt(&(ra.ph->bx))/2;
                   1620:                rcos = cos(tra->rot);  rsin = sin(tra->rot);
                   1621:                for(ory=sy; ory<=ey; ory++) {
                   1622:                        opel=0; /* left of output margin: assume pel==0 */
                   1623:                        rp=rl.r-1;
                   1624:                        irx = ((rcos*(sx - ce.x) - rsin*(ory - ce.y))) + ce.x;
                   1625:                        iry = ((rsin*(sx - ce.x) + rcos*(ory - ce.y))) + ce.y;
                   1626:                        for(orx=sx; orx<=ex; orx++) {
                   1627:                                rx = (int)(irx + 0.5);  ry = (int)(iry + 0.5);
                   1628:                                if(rx<sx || rx>ex || ry<sy || ry>ey)
                   1629:                                        /* outside input image:  assume pel==0 */
                   1630:                                        pel=0;
                   1631:                                else /* look at bit within input image */ {
                   1632:                                    int ix,iy,bx;
                   1633:                                        iy = (ry-sy)*ipl;
                   1634:                                        ix = rx/BITS_PER_INT;
                   1635:                                        bx = rx%BITS_PER_INT;
                   1636: #if BIG_ENDIAN
                   1637:                                        pel = (buf[ iy + ix ] & (01<<(BITS_PER_INT-bx-1))) ? 1 : 0;
                   1638: #else
                   1639:                                        pel = (buf[ iy + ix ] & (01<<bx)) ? 1 : 0;
                   1640: #endif
                   1641:                                        };
                   1642:                                if(pel!=opel) {
                   1643:                                        if(opel) { rp->xe=orx-1;  opel=0; }
                   1644:                                        else { (++rp)->xs=orx;  opel=pel; };
                   1645:                                        };
                   1646:                                /* step one pel to the right in output image */
                   1647:                                irx += rcos;  iry += rsin;
                   1648:                                };
                   1649:                        if(opel) rp->xe=orx-1;
                   1650:                        rl.runs = rp - rl.r + 1;
                   1651:                        rl.y = ory;
                   1652:                        sink(&rl,&ra);
                   1653:                        };
                   1654:                }
                   1655:        else {  abort("rotate_binary_buffer: tra->rot==%g deg unimplemented",
                   1656:                        tra->rot/DtoR);
                   1657:                };
                   1658:        sink(NULL,&ra); /* signal end-of-page */
                   1659:        }
                   1660: 
                   1661: /* Copy a source of RLE_Lines to a sink of RLE_Lines, transforming them
                   1662:    by trimming, shifting, scaling, truncation, and rotation.
                   1663:       The source is function ir(), which returns non-empty lines only,
                   1664:    or NULL on end of page.  It is passed `bop=T' on beginning of page.
                   1665:    On return from ir(), ia->ph->cy holds the index of the line, whose height is
                   1666:    guaranteed to lie in the range [ia->ph->bx.a.y,ia->ph->bx.b.y].
                   1667:    All input runs are guaranteed to lie in [ia->ph->bx.a.x,ia->ph->bx.b.x].
                   1668:    The maximum length (in pels) of each source line is ia->wid.
                   1669:       The sink function or() takes two arguments:
                   1670:        RLE_Line *rl;   ==NULL on end-of-page
                   1671:        Copy_arg *a;
                   1672:    The lines sent to the sink must be in unbroken ascending integer 
                   1673:    sequence of rl->y (thus blank lines must be explicitly sent).   At all times,
                   1674:    oa->ph->cy is the line last written.  After the first call to or(),
                   1675:    oa->ph->cy lies in the range [oa->ph->bx.a.y,oa->ph->bx.b.y].
                   1676:       Trimming, shifting, scaling, and truncation are performed either
                   1677:    here or in  function transform_rlel().  Rotation is handled specially:
                   1678:    the complete output image (after all other transformations have been
                   1679:    performed) is saved in an intermediate buffer (as packed binary), then
                   1680:    rotated.  Rotation is much slower than the other operations, mainly due
                   1681:    to the necessity of touching every pixel.  (Manhattan rotations might be
                   1682:    faster if the buffer held RLE_lines, but then it would be next-to-impossible
                   1683:    to extend to arbitrary rotations someday.)
                   1684:    */
                   1685: transform_rlels(ir,ia,or,oa,tra)
                   1686:     RLE_Line *(*ir)(); /* return next RLE_Line */
                   1687:     Copy_arg *ia;      /* used here (bop & wid) & passed to ir() */
                   1688:     int (*or)();       /* write next RLE_Line */
                   1689:     Copy_arg *oa;      /* used here (bop && ph->bx.*.y) & passed to or() */
                   1690:     Transform_rlel_arg *tra;
                   1691: {   RLE_Line *irl,*orl;
                   1692:     static RLE_Line rl0 = Init_RLE_Line;  /* empty line */
                   1693:     int tr_y;          /* transformed y */
                   1694:     int (*sv_or)();
                   1695:        if(tra->rot!=0.0) {
                   1696:                /* if must rotate the image, first buffer the entire
                   1697:                   set of output RLE_Lines */
                   1698:                sv_or = or;
                   1699:                or = (int (*)())binary_buffer;
                   1700:                };
                   1701:        /* signal beginning of page; reset in source() & sink() functions */
                   1702:        ia->bop=oa->bop=T;      
                   1703:        /* set first output line number to write */
                   1704:        tra->dy = (tra->sy = oa->ph->bx.a.y);
                   1705:        while((irl=ir(ia))!=NULL) {
                   1706:                if(F&&_O.dbg_r) nerr_RLE_Line("trans.i: ",irl);
                   1707:                /* trim input lines' Y */
                   1708:                if(irl->y < tra->tr.a.y) continue;
                   1709:                if(irl->y > tra->tr.b.y) break;
                   1710:                /* compute the output Y that is equal to the last
                   1711:                   of the group of transformed equivalent Y's */
                   1712:                tr_y = (int)((irl->y + tra->off.y + 1)*tra->scl.y) - 1;
                   1713:                /* truncate if necessary */
                   1714:                if(tr_y>oa->ph->bx.b.y) tr_y = oa->ph->bx.b.y;
                   1715:                /* supply implicit blank line(s) of the same length */
                   1716:                while(tra->sy < tr_y) {
                   1717:                        rl0.len = ia->wid;
                   1718:                        transform_rlel(&rl0,tra,or,oa);
                   1719:                        };
                   1720:                irl->len = ia->wid;
                   1721:                transform_rlel(irl,tra,or,oa);
                   1722:                };
                   1723:        /* supply terminating blank line(s) of the same length */
                   1724:        while(tra->sy < oa->ph->bx.b.y) {
                   1725:                rl0.len = ia->wid;
                   1726:                transform_rlel(&rl0,tra,or,oa);
                   1727:                };
                   1728:        transform_rlel(NULL,tra,or,oa);   /* signal end of page */
                   1729:        /* read input until end of page occurs; this is required
                   1730:           to support catenated pages */
                   1731:        while(irl!=NULL) irl=ir(ia);
                   1732:        if(tra->rot!=0.0) {
                   1733:            unsigned int *buf;
                   1734:                buf = binary_buffer(NULL,NULL);
                   1735:                if(buf!=NULL) { 
                   1736:                        rotate_binary_buffer(buf,tra,sv_or,oa);
                   1737:                        free(buf);
                   1738:                        };
                   1739:                };
                   1740:        }
                   1741: 
                   1742: process_page(i,o)
                   1743:     Copy_arg *i,*o;
                   1744: {   RLE_Line *(*source)();
                   1745:     int (*sink)();
                   1746:     char unit,*up,cpy[40];             /* units character */
                   1747:     Transform_rlel_arg tra;
                   1748: 
                   1749:        i->wid = bbx_wid(&(i->ph->bx));
                   1750: 
                   1751:        _O.trim = max_Bbx;      /* start by trimming nothing */
                   1752:        /* translate units in option arguments */
                   1753:        if(_O.optarg_l!=NULL) {
                   1754:                strcpy(cpy,_O.optarg_l);
                   1755:                if((up=strpbrk(cpy,UNITS))!=NULL) {
                   1756:                        unit= *up;  *up='\0';
                   1757:                        _O.trim.a.x=vto_scoor(atof(cpy),unit,i->ph->res_x);
                   1758:                        }
                   1759:                else /* assume scanner coordinates */
                   1760:                        _O.trim.a.x=atoi(cpy);
                   1761:                };
                   1762:        if(_O.optarg_r!=NULL) {
                   1763:                strcpy(cpy,_O.optarg_r);
                   1764:                if((up=strpbrk(cpy,UNITS))!=NULL) {
                   1765:                        unit= *up;  *up='\0';
                   1766:                        _O.trim.b.x=vto_scoor(atof(cpy),unit,i->ph->res_x);
                   1767:                        }
                   1768:                else /* assume scanner coordinates */
                   1769:                        _O.trim.b.x=atoi(cpy);
                   1770:                _O.trim.b.x--;  /* -w coordinate is open, Bbx is closed */
                   1771:                };
                   1772:        if(_O.optarg_t!=NULL) {
                   1773:                strcpy(cpy,_O.optarg_t);
                   1774:                if((up=strpbrk(cpy,UNITS))!=NULL) {
                   1775:                        unit= *up;  *up='\0';
                   1776:                        _O.trim.a.y=vto_scoor(atof(cpy),unit,i->ph->res_y);
                   1777:                        }
                   1778:                else /* assume scanner coordinates */
                   1779:                        _O.trim.a.y=atoi(cpy);
                   1780:                };
                   1781:        if(_O.optarg_b!=NULL) {
                   1782:                strcpy(cpy,_O.optarg_b);
                   1783:                if((up=strpbrk(cpy,UNITS))!=NULL) {
                   1784:                        unit= *up;  *up='\0';
                   1785:                        _O.trim.b.y=vto_scoor(atof(cpy),unit,i->ph->res_y);
                   1786:                        }
                   1787:                else /* assume scanner coordinates */
                   1788:                        _O.trim.b.y=atoi(cpy);
                   1789:                _O.trim.b.y--;  /* -w coordinate is open, Bbx is closed */
                   1790:                };
                   1791:        /* Modified output margins may lie OUTSIDE the input window as well
                   1792:           as within it. */
                   1793:        if(_O.trim.a.x==Scoor_MIN) _O.trim.a.x=i->ph->bx.a.x;
                   1794:        if(_O.trim.b.x==Scoor_MAX) _O.trim.b.x=i->ph->bx.b.x;
                   1795:        if(_O.trim.a.y==Scoor_MIN) _O.trim.a.y=i->ph->bx.a.y;
                   1796:        if(_O.trim.b.y==Scoor_MAX) _O.trim.b.y=i->ph->bx.b.y;
                   1797:        if(_O.dbg_m) err("trim: %s",bbx_toa(&(_O.trim)));
                   1798: 
                   1799:        if(strcmp(i->ph->type,"binary")==0) { source = binary_source; }
                   1800:        else if(strcmp(i->ph->type,"bitmap")==0) { source = bitmap_source; }
                   1801:        else if(strcmp(i->ph->type,"bitfile")==0) { source = bitfile_source; }
                   1802:        else if(strcmp(i->ph->type,"document-image")==0) { source = dim_source; }
                   1803:        else if(strcmp(i->ph->type,"dim")==0) { source = dim_source; }
                   1804:        else if(strcmp(i->ph->type,"rle")==0) {
                   1805:            RIC_hdr rh;
                   1806:                /* reopen RLE file to use system I/O (awkward, obsolescent) */
                   1807:                lseek(fileno(i->ph->fp),0L,0);
                   1808:                RLE_open(fileno(i->ph->fp),&rh);
                   1809:                i->ph->cy = i->ph->bx.a.y-1;
                   1810:                source = rle_source;
                   1811:                }
                   1812:        else if(strcmp(i->ph->type,"pico")==0
                   1813:                ||strcmp(i->ph->type,"dump")==0) {
                   1814:                i->thresh = _O.thresh;
                   1815:                source = pic_source;
                   1816:                }
                   1817:        else if(strcmp(i->ph->type,"ccitt-g31")==0) {
                   1818:                if((i->bf=bopen(i->ph->fp,"r"))==NULL)
                   1819:                        abort("can't open bitfile");
                   1820:                i->tbl = ccitt_table();
                   1821:                source = g31_source;
                   1822:                }
                   1823:        else if(strcmp(i->ph->type,"ccitt-g32")==0) {
                   1824:                if((i->bf=bopen(i->ph->fp,"r"))==NULL)
                   1825:                        abort("can't open bitfile");
                   1826:                i->tbl = ccitt_table();
                   1827:                source = g32_source;
                   1828:                }
                   1829:        else if(strcmp(i->ph->type,"ccitt-g4")==0) {
                   1830:                if((i->bf=bopen(i->ph->fp,"r"))==NULL)
                   1831:                        abort("can't open bitfile");
                   1832:                i->tbl = ccitt_table();
                   1833:                source = g4_source;
                   1834:                }
                   1835:        else if(strcmp(i->ph->type,"cdf-mrlc")==0) { source = cdf_mrlc_source; }
                   1836:        else abort("Input file TYPE=%s unsupported",i->ph->type);
                   1837: 
                   1838:        if(_O.dbg_h) err("In %s",PIC_hdr_toa(i->ph));
                   1839: 
                   1840:        /* Adjudicate -R and -x options */
                   1841:        if(_O.out_res.x==-2) {
                   1842:                /* -R= specified:  force resolutions to be equal to the greater */
                   1843:                if(i->ph->res_x < i->ph->res_y) {
                   1844:                        _O.out_res.x = _O.out_res.y = i->ph->res_y;
                   1845:                        }
                   1846:                else if(i->ph->res_y < i->ph->res_x) {
                   1847:                        _O.out_res.x = _O.out_res.y = i->ph->res_x;
                   1848:                        }
                   1849:                else _O.out_res.x = _O.out_res.y = i->ph->res_x;
                   1850:                };
                   1851:        if(_O.out_res.x!=-1) {  /* -Rx specified; override -xX */
                   1852:                _O.expand.x = ((double)_O.out_res.x)/i->ph->res_x;
                   1853:                if(_O.dbg_R && _O.expand.x!=1.0)
                   1854:                        err("horizontal resolution changed: x%g (%d -> %d)",
                   1855:                                _O.expand.x,i->ph->res_x,_O.out_res.x);
                   1856:                };
                   1857:        if(_O.out_res.y!=-1) {  /* -R,y specified; override -x,Y */
                   1858:                _O.expand.y = ((double)_O.out_res.y)/i->ph->res_y;
                   1859:                if(_O.dbg_R && _O.expand.y!=1.0)
                   1860:                        err("vertical resolution changed: x%g (%d -> %d)",
                   1861:                                _O.expand.y,i->ph->res_y,_O.out_res.y);
                   1862:                };
                   1863: 
                   1864:        /* Setup image transformation parameters */
                   1865:        tra = empty_Transform_rlel_arg;
                   1866:        tra.tr = _O.trim;
                   1867:        tra.off = _O.offset;
                   1868:        tra.scl = _O.expand;
                   1869:        tra.wh.x = bbx_wid(&(tra.tr));
                   1870:        tra.wh.y = bbx_hgt(&(tra.tr));
                   1871:        tra.rev = _O.reverse;
                   1872:        if(tra.scl.x!=1.0) {
                   1873:                tra.wh.x = (int)(tra.wh.x*tra.scl.x+0.5);
                   1874:                };
                   1875:        if(tra.scl.y!=1.0) {
                   1876:                tra.wh.y = (int)(tra.wh.y*tra.scl.y+0.5);
                   1877:                };
                   1878:        switch(_O.top) {
                   1879:            case 't':  /* default */ break;
                   1880:            case 'l':  /* top is really at left */
                   1881:                tra.rot = (Radians)(PI/2);
                   1882:                break;
                   1883:            case 'b':  /* top is really at bottom */
                   1884:                tra.rot = (Radians)(PI);
                   1885:                break;
                   1886:            case 'r':  /* top is really at right */
                   1887:                tra.rot = (Radians)((3*PI)/2);
                   1888:                break;
                   1889:            case 'a':  /* rotation angle given */
                   1890:                tra.rot = _O.top_angle;
                   1891:                break;
                   1892:            };
                   1893:        /* is the transform the identity? (speed-optimized special case) */
                   1894:        tra.ident = ( (bbx_eq(&(tra.tr),&(i->ph->bx)))
                   1895:                        && (tra.scl.x==1.0)
                   1896:                        && (tra.scl.y==1.0)
                   1897:                        && (tra.off.x==0)
                   1898:                        && (tra.off.y==0)
                   1899:                        && (tra.rot==0.0) );
                   1900: 
                   1901:        /* compute transformed output box & resolution;
                   1902:           don't rotate here (see transform_rlels()) */
                   1903:        if(tra.ident) {
                   1904:                o->ph->bx = i->ph->bx;
                   1905:                o->ph->res_x = i->ph->res_x;
                   1906:                o->ph->res_y = i->ph->res_y;
                   1907:                }
                   1908:        else {  o->ph->bx = tra.tr;
                   1909:                o->ph->bx.a.x += tra.off.x;
                   1910:                o->ph->bx.b.x += tra.off.x;
                   1911:                o->ph->bx.a.y += tra.off.y;
                   1912:                o->ph->bx.b.y += tra.off.y;
                   1913:                if(tra.scl.x!=1.0) {
                   1914:                        o->ph->bx.a.x = tra.scl.x*o->ph->bx.a.x;
                   1915:                        o->ph->bx.b.x = o->ph->bx.a.x + tra.wh.x-1;
                   1916:                        };
                   1917:                if(tra.scl.y!=1.0) {
                   1918:                        o->ph->bx.a.y = tra.scl.y*o->ph->bx.a.y;
                   1919:                        o->ph->bx.b.y = o->ph->bx.a.y + tra.wh.y-1;
                   1920:                        };
                   1921:                o->ph->res_x = (i->ph->res_x*tra.scl.x + 0.5);
                   1922:                o->ph->res_y = (i->ph->res_y*tra.scl.y + 0.5);
                   1923:                };
                   1924: 
                   1925:        if(_O.to_bin)
                   1926:                { strcpy(o->ph->type,"binary"); sink = binary_sink; }
                   1927:        else if(_O.to_bitfile)
                   1928:                { strcpy(o->ph->type,"bitfile"); sink = bitfile_sink; }
                   1929:        else if(_O.to_bitmap)
                   1930:                { strcpy(o->ph->type,"bitmap"); sink = bitmap_sink; }
                   1931:        else if (_O.to_rle) {
                   1932:                if(strcmp(i->ph->type,"rle")==0)
                   1933:                        abort("can't both read and write TYPE=rle - sorry");
                   1934:                strcpy(o->ph->type,"rle"); sink = rle_sink;
                   1935:                }
                   1936:        else if(_O.to_g31) { strcpy(o->ph->type,"ccitt-g31"); sink = g31_sink; }
                   1937:        else if(_O.to_g32) {
                   1938:                strcpy(o->ph->type,"ccitt-g32");
                   1939:                o->k = _O.g32_k;
                   1940:                sink = g32_sink;
                   1941:                }
                   1942:        else if(_O.to_g4) { strcpy(o->ph->type,"ccitt-g4");  sink = g4_sink; }
                   1943:        else if(_O.to_pic) { strcpy(o->ph->type,"dump");  sink = pic_sink; }
                   1944: #if CPU==SUN
                   1945:        else if(_O.to_post) { strcpy(o->ph->type,"postscript"); sink = post_sink; }
                   1946: #endif
                   1947: #if CPU==SUN
                   1948:        else if(_O.to_rast) { strcpy(o->ph->type,"sunraster"); sink = rast_sink; }
                   1949: #endif
                   1950:        if(i->ph->misc!=NULL) {
                   1951:                o->ph->misc = i->ph->misc;
                   1952:                i->ph->misc = NULL;
                   1953:                };
                   1954:        if(_O.dbg_h) err("Out %s",PIC_hdr_toa(o->ph));
                   1955: 
                   1956:        transform_rlels(source,i,sink,o,&tra);
                   1957: 
                   1958:        /* Synchronize filedes pointer with stream pointer */
                   1959:        lseek(fileno(o->ph->fp),o->ph->seek = ftell(o->ph->fp),0);
                   1960:        }
                   1961: 
                   1962: /* A file may be a catenation of pages. */
                   1963: process_fps(i,o)
                   1964:     FILE *i,*o;
                   1965: {   Copy_arg ia,oa;
                   1966:     int stat;
                   1967:        ia = oa = empty_Copy_arg;
                   1968:        ia.ph = alloc_PIC_hdr(i);
                   1969:        oa.ph = alloc_PIC_hdr(o);
                   1970: 
                   1971:        stat=PIC_get_hdr(ia.ph);
                   1972:        if(_O.dbg_h && stat!=1) err("PIC_get_hdr() returns status %d",stat);
                   1973: 
                   1974:        /* enforce bitfile(9) I/O restrictions */
                   1975:        if(_O.from_bitfile && strcmp(ia.ph->type,"bitfile")!=0)
                   1976:                abort("-Bi requires input to be bitfile(9.5) format");
                   1977:        if(!_O.from_bitfile && strcmp(ia.ph->type,"bitfile")==0) {
                   1978:                /* TYPE= is missing, erroneously:  refuse to recognize it */
                   1979:                abort("TYPE=... header is missing");
                   1980:                };
                   1981: 
                   1982:        if(strcmp(ia.ph->type,"document-image")==0
                   1983:           || strcmp(ia.ph->type,"dim")==0) {
                   1984:            Page pg;
                   1985:                skip_doc(i);
                   1986:                if(frdb_page_etc(i,&pg,IsALL)==1) {
                   1987:                        ia.ph->bx = pg.bx;
                   1988:                        ia.ph->res_x = pg.res_x;
                   1989:                        ia.ph->res_y = pg.res_y;
                   1990:                        ia.rles = *rle_lines_of_page(&pg);
                   1991:                        if(_O.shrinkwrap!=-1) {
                   1992:                            Sp trans;
                   1993:                                ia.ph->bx = *bbx_of_rle_lines(&ia.rles);
                   1994:                                ia.ph->bx.a.x -= _O.shrinkwrap;
                   1995:                                ia.ph->bx.a.y -= _O.shrinkwrap;
                   1996:                                ia.ph->bx.b.x += _O.shrinkwrap;
                   1997:                                ia.ph->bx.b.y += _O.shrinkwrap;
                   1998:                                if(bbx_area(&(ia.ph->bx))<=0)
                   1999:                                    abort("-W%d shrinks to nothing",_O.shrinkwrap);
                   2000:                                trans.x = -ia.ph->bx.a.x; trans.y = -ia.ph->bx.a.y;
                   2001:                                translate_rle_lines(&ia.rles,trans);
                   2002:                                ia.ph->bx.b.x = bbx_wid(&ia.ph->bx)-1;
                   2003:                                ia.ph->bx.b.y = bbx_hgt(&ia.ph->bx)-1;
                   2004:                                ia.ph->bx.a.x = ia.ph->bx.a.y = 0;
                   2005:                                };
                   2006:                        free_page_etc(&pg,IsALL&(~IsPage));
                   2007:                        }
                   2008:                else {  free_page_etc(&pg,IsALL&(~IsPage));
                   2009:                        abort("can't read document-image file");
                   2010:                        };
                   2011:                };
                   2012:        if(_O.in_res.x!=SHRT_MIN&&_O.in_res.y!=SHRT_MIN) {
                   2013:                /* force input RES to given values */
                   2014:                if(ia.ph->res_x!=0 || ia.ph->res_y!=0) {
                   2015:                        err("input: RES=%d %d overridden by -Z%d,%d\n",
                   2016:                                ia.ph->res_x,ia.ph->res_y,_O.in_res.x,_O.in_res.y);
                   2017:                        };
                   2018:                ia.ph->res_x = _O.in_res.x;
                   2019:                ia.ph->res_y = _O.in_res.y;
                   2020:                };
                   2021:        if(ia.ph->res_x<=0 || ia.ph->res_y<=0)
                   2022:                err("input: RES=%d %d may cause problems (set using -Zx,y)",
                   2023:                        ia.ph->res_x,ia.ph->res_y);
                   2024: 
                   2025:        while(strlen(ia.ph->type)>0 && stat==1 && !feof(i)
                   2026:                && !ferror(i) && !ferror(o)) {
                   2027:                process_page(&ia,&oa);
                   2028:                if( strcmp(ia.ph->type,"cdf")==0
                   2029:                    || strcmp(ia.ph->type,"cdf-mrlc")==0 ) {
                   2030:                        stat=CDF_next_page(ia.ph);
                   2031:                        }
                   2032:                else {  if((stat=PIC_get_hdr(ia.ph))==1) {
                   2033:                                /* enforce bitfile(9) I/O restrictions */
                   2034:                                if(_O.from_bitfile && strcmp(ia.ph->type,"bitfile")!=0)
                   2035:                                        abort("-Bi means input must be picfile");
                   2036:                                if(!_O.from_bitfile && strcmp(ia.ph->type,"bitfile")==0) {
                   2037:                                        /* TYPE= is missing, erroneously:  silently quit */
                   2038:                                        if(_O.dbg_h) err("strange input before normal EOF - ignored");
                   2039:                                        strcpy(ia.ph->type,"");
                   2040:                                        };
                   2041:                                };
                   2042:                        };
                   2043:                if(_O.dbg_h && stat!=1)
                   2044:                        err("PIC_get_hdr() returns status %d",stat);
                   2045:                };
                   2046: 
                   2047:        /* EOF or error */
                   2048:        free_PIC_hdr(ia.ph);
                   2049:        free_PIC_hdr(oa.ph);
                   2050:        }
                   2051: 
                   2052: #if FILE_TREE
                   2053: /* Process filenames:  if NULL, use stdin/stdout;  if files, read them;
                   2054:    if directories, create a parallel file tree and process the leaves
                   2055:    pairwise. */
                   2056: process_fns(i,o)
                   2057:     char *i;           /* may be NULL; not yet fopened for read */
                   2058:     char *o;           /* may be NULL; not yet fopened for write */
                   2059: #define dbg_ft (F)
                   2060: {   FILE *i_fp;
                   2061:     FILE *o_fp;
                   2062:     char *branch;
                   2063:        if(dbg_ft) err("processs(\"%s\",\"%s\")",i,o);
                   2064:        branch=path_toa(&path_process.path,1);
                   2065:        if(dbg_ft&&branch[0]!='\0') err("%s",branch);
                   2066:        if(i==NULL||i[0]=='\0') i_fp=stdin;
                   2067:        else if( (i_fp=fopen(i,"r"))==NULL ) {
                   2068:                err("can't open input file %s - skip it",i);
                   2069:                return;
                   2070:                };
                   2071:        if(o==NULL||o[0]=='\0') o_fp=stdout;
                   2072:        else if( (o_fp=fopen(o,"w"))==NULL ) {
                   2073:                err("can't open output file %s - skip it",o);
                   2074:                return;
                   2075:                };
                   2076:        process_fps(i_fp,o_fp);
                   2077:        if(i_fp!=stdin) fclose(i_fp);
                   2078:        if(o_fp!=stdout) fclose(o_fp); else fflush(o_fp);
                   2079:        };
                   2080: #else
                   2081: /* Process filenames:  if NULL, use stdin/stdout;  if files, open and process them.
                   2082:    */
                   2083: process_fns(i_fn,o_fn)
                   2084:     char *i_fn;                /* may be NULL; not yet fopened for read */
                   2085:     char *o_fn;                /* may be NULL; not yet fopened for write */
                   2086: {   FILE *i_fp;
                   2087:     FILE *o_fp;
                   2088:        if(i_fn==NULL||strlen(i_fn)==0) i_fp = stdin;
                   2089:        else {  if((i_fp=fopen(i_fn,"r"))==NULL)
                   2090:                        abort("can't open input file %s",i_fn);
                   2091:                };
                   2092:        if(o_fn==NULL||strlen(o_fn)==0) o_fp = stdout;
                   2093:        else {  if((o_fp=fopen(o_fn,"w"))==NULL)
                   2094:                        abort("can't open output file %s",o_fn);
                   2095:                };
                   2096:        process_fps(i_fp,o_fp);
                   2097:        if(i_fp!=stdin) fclose(i_fp);
                   2098:        if(o_fp!=stdout) fclose(o_fp); else fflush(o_fp);
                   2099:        };
                   2100: #endif
                   2101: 
                   2102: main(arc,arv)
                   2103:     int arc; char **arv;
                   2104: {      parse_args(arc,arv);
                   2105: #if FILE_TREE
                   2106:        process_file_trees(process_fns,_O.in_fn,_O.out_fn);
                   2107: #else
                   2108:        process_fns(_O.in_fn,_O.out_fn);
                   2109: #endif
                   2110:        }
                   2111: 
                   2112: nerr_RLE_Line(s,rl)
                   2113:     char *s;
                   2114:     RLE_Line *rl;
                   2115: {   RLE_Run *r;
                   2116:     int ri;
                   2117:        if(rl==NULL) fprintf(stderr,"%15s RLEL NULL.\n",s);
                   2118:        else {  fprintf(stderr,"%15s RLEL y%d r%d l%d: ",s,rl->y,rl->runs,rl->len);
                   2119:                for(ri=0,r=rl->r; ri<rl->runs; ri++,r++)
                   2120:                        fprintf(stderr,"[%d,%d] ",r->xs,r->xe);
                   2121:                fprintf(stderr,"\n");
                   2122:                };
                   2123:        }

unix.superglobalmegacorp.com

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