|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.