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

1.1     ! root        1: /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved.              */
        !             2: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T.                */
        !             3: /* The copyright notice does not imply actual or intended publication. */
        !             4: /* AUTHORS:                                            */
        !             5: /*     H. S. Baird - ATT-BL MH - first versions        */
        !             6: /*     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.