| 1 |  | #ifndef lint | 
| 2 | < | static const char       RCSid[] = "$Id$"; | 
| 2 | > | static const char RCSid[] = "$Id$"; | 
| 3 |  | #endif | 
| 4 |  | /* | 
| 5 |  | *  pfilt.c - program to post-process picture file. | 
| 8 |  | *     6/23/93  Added additional buffers for value spreading | 
| 9 |  | */ | 
| 10 |  |  | 
| 11 | < | #include  "standard.h" | 
| 11 | > | #include  "copyright.h" | 
| 12 |  |  | 
| 13 |  | #include  <signal.h> | 
| 14 | < |  | 
| 15 | < | #include  "color.h" | 
| 16 | < |  | 
| 14 | > | #include  "pfilt.h" | 
| 15 | > | #include  "platform.h" | 
| 16 | > | #include  "paths.h" | 
| 17 |  | #include  "view.h" | 
| 18 |  |  | 
| 19 | – | #include  "paths.h" | 
| 20 | – |  | 
| 21 | – | extern float  *matchlamp(); | 
| 22 | – |  | 
| 19 |  | #define  FEQ(a,b)       ((a) >= .98*(b) && (a) <= 1.02*(b)) | 
| 20 |  |  | 
| 21 | < | double   CHECKRAD = 1.5;        /* radius to check for filtering */ | 
| 21 | > | double   CHECKRAD = 2.0;        /* radius to check for filtering */ | 
| 22 |  |  | 
| 23 |  | #define  THRESHRAD      5.0     /* maximum sample spread in output */ | 
| 24 |  |  | 
| 69 |  | int  ybrad;                     /* y box size */ | 
| 70 |  |  | 
| 71 |  | int  barsize;                   /* size of input scan bar */ | 
| 72 | < | COLOR  **scanin;                /* input scan bar */ | 
| 73 | < | COLOR  *scanout;                /* output scan line */ | 
| 74 | < | COLOR  **scoutbar;              /* output scan bar (if thresh > 0) */ | 
| 72 | > | COLORV  **scanin;               /* input scan bar */ | 
| 73 | > | COLORV  *scanout;               /* output scan line */ | 
| 74 | > | COLORV  **scoutbar;             /* output scan bar (if thresh > 0) */ | 
| 75 |  | float  **greybar;               /* grey-averaged input values */ | 
| 76 |  | int  obarsize = 0;              /* size of output scan bar */ | 
| 77 |  | int  orad = 0;                  /* output window radius */ | 
| 78 |  |  | 
| 79 |  | char  *progname; | 
| 80 |  |  | 
| 81 | + | static gethfunc headline; | 
| 82 | + | static void copyfile(FILE  *in, FILE  *out); | 
| 83 | + | static void pass1(FILE  *in); | 
| 84 | + | static void pass2(FILE  *in); | 
| 85 | + | static void scan2init(void); | 
| 86 | + | static void scan2sync(int  r); | 
| 87 | + | static void scan2flush(void); | 
| 88 |  |  | 
| 89 | < | main(argc, argv) | 
| 90 | < | int  argc; | 
| 91 | < | char  **argv; | 
| 89 | > |  | 
| 90 | > | int | 
| 91 | > | main( | 
| 92 | > | int  argc, | 
| 93 | > | char  **argv | 
| 94 | > | ) | 
| 95 |  | { | 
| 90 | – | extern int  headline(); | 
| 96 |  | FILE  *fin; | 
| 97 |  | float  *lampcolor; | 
| 98 |  | char  *lamptype = NULL; | 
| 100 |  | double  outaspect = 0.0; | 
| 101 |  | double  d; | 
| 102 |  | int  i, j; | 
| 103 | < | #ifdef MSDOS | 
| 104 | < | extern int  _fmode; | 
| 105 | < | _fmode = O_BINARY; | 
| 101 | < | setmode(fileno(stdin), O_BINARY); | 
| 102 | < | setmode(fileno(stdout), O_BINARY); | 
| 103 | < | #endif | 
| 103 | > | SET_DEFAULT_BINARY(); | 
| 104 | > | SET_FILE_BINARY(stdin); | 
| 105 | > | SET_FILE_BINARY(stdout); | 
| 106 |  | if (signal(SIGINT, quit) == SIG_IGN) | 
| 107 |  | signal(SIGINT, SIG_IGN); | 
| 108 | + | #ifdef SIGHUP | 
| 109 |  | if (signal(SIGHUP, quit) == SIG_IGN) | 
| 110 |  | signal(SIGHUP, SIG_IGN); | 
| 111 | + | #endif | 
| 112 |  | signal(SIGTERM, quit); | 
| 113 | + | #ifdef SIGPIPE | 
| 114 |  | signal(SIGPIPE, quit); | 
| 115 | + | #endif | 
| 116 |  | #ifdef  SIGXCPU | 
| 117 |  | signal(SIGXCPU, quit); | 
| 118 |  | signal(SIGXFSZ, quit); | 
| 266 |  | progname); | 
| 267 |  | quit(1); | 
| 268 |  | } | 
| 269 | + | if (NCSAMP < 3) { | 
| 270 | + | fprintf(stderr, "%s: bad number of components\n", progname); | 
| 271 | + | quit(1); | 
| 272 | + | } | 
| 273 |  | /* add new header info. */ | 
| 274 |  | printargs(i, argv, stdout); | 
| 275 |  | /* get picture size */ | 
| 314 |  | pass2(fin); | 
| 315 |  |  | 
| 316 |  | quit(estatus); | 
| 317 | + | return estatus; /* pro forma return */ | 
| 318 |  | } | 
| 319 |  |  | 
| 320 |  |  | 
| 321 | < | double | 
| 322 | < | rgb_bright(clr) | 
| 323 | < | COLOR  clr; | 
| 321 | > | static double | 
| 322 | > | rgb_bright( | 
| 323 | > | SCOLOR  clr | 
| 324 | > | ) | 
| 325 |  | { | 
| 326 |  | return(bright(clr)); | 
| 327 |  | } | 
| 328 |  |  | 
| 329 |  |  | 
| 330 | < | double | 
| 331 | < | xyz_bright(clr) | 
| 332 | < | COLOR  clr; | 
| 330 | > | static double | 
| 331 | > | xyz_bright( | 
| 332 | > | SCOLOR  clr | 
| 333 | > | ) | 
| 334 |  | { | 
| 335 | < | return(clr[CIEY]); | 
| 335 | > | return(colval(clr,CIEY)); | 
| 336 |  | } | 
| 337 |  |  | 
| 338 |  |  | 
| 339 | < | double  (*ourbright)() = rgb_bright; | 
| 339 | > | static double | 
| 340 | > | spec_bright( | 
| 341 | > | SCOLOR  clr | 
| 342 | > | ) | 
| 343 | > | { | 
| 344 | > | return(pbright(clr)); | 
| 345 | > | } | 
| 346 |  |  | 
| 347 |  |  | 
| 348 | < | int | 
| 349 | < | headline(s)                             /* process line from header */ | 
| 350 | < | char  *s; | 
| 348 | > | brightfunc_t *ourbright = rgb_bright; | 
| 349 | > |  | 
| 350 | > | static int | 
| 351 | > | headline(                               /* process line from header */ | 
| 352 | > | char    *s, | 
| 353 | > | void    *p | 
| 354 | > | ) | 
| 355 |  | { | 
| 356 | < | char  fmt[32]; | 
| 356 | > | char  fmt[MAXFMTLEN]; | 
| 357 |  |  | 
| 358 |  | fputs(s, stdout);               /* copy to output */ | 
| 359 |  | if (isaspect(s))                /* get aspect ratio */ | 
| 360 |  | inpaspect *= aspectval(s); | 
| 361 |  | else if (isexpos(s))            /* get exposure */ | 
| 362 |  | hotlvl *= exposval(s); | 
| 363 | + | else if (isncomp(s))            /* get #components (spectral) */ | 
| 364 | + | NCSAMP = ncompval(s); | 
| 365 | + | else if (iswlsplit(s))          /* get wavelength partitions */ | 
| 366 | + | wlsplitval(WLPART, s); | 
| 367 |  | else if (formatval(fmt, s)) {   /* get format */ | 
| 368 |  | wrongformat = 0; | 
| 369 |  | if (!strcmp(COLRFMT, fmt)) | 
| 370 |  | ourbright = rgb_bright; | 
| 371 |  | else if (!strcmp(CIEFMT, fmt)) | 
| 372 |  | ourbright = xyz_bright; | 
| 373 | + | else if (!strcmp(SPECFMT, fmt)) | 
| 374 | + | ourbright = spec_bright; | 
| 375 |  | else | 
| 376 |  | wrongformat = !globmatch(PICFMT, fmt); | 
| 377 |  | } else if (isview(s) && sscanview(&ourview, s) > 0) | 
| 380 |  | } | 
| 381 |  |  | 
| 382 |  |  | 
| 383 | < | copyfile(in, out)                       /* copy a file */ | 
| 384 | < | register FILE  *in, *out; | 
| 383 | > | static void | 
| 384 | > | copyfile(                       /* copy a file */ | 
| 385 | > | FILE  *in, | 
| 386 | > | FILE  *out | 
| 387 | > | ) | 
| 388 |  | { | 
| 389 | < | register int  c; | 
| 389 | > | int  c; | 
| 390 |  |  | 
| 391 |  | while ((c = getc(in)) != EOF) | 
| 392 |  | putc(c, out); | 
| 398 |  | } | 
| 399 |  |  | 
| 400 |  |  | 
| 401 | < | pass1(in)                               /* first pass of picture file */ | 
| 402 | < | FILE  *in; | 
| 401 | > | static void | 
| 402 | > | pass1(                          /* first pass of picture file */ | 
| 403 | > | FILE  *in | 
| 404 | > | ) | 
| 405 |  | { | 
| 406 |  | int  i; | 
| 407 | < | COLOR  *scan; | 
| 407 | > | COLORV  *scan; | 
| 408 |  |  | 
| 409 |  | pass1init(); | 
| 410 |  |  | 
| 411 | < | scan = (COLOR *)malloc(xres*sizeof(COLOR)); | 
| 411 | > | scan = (COLORV *)malloc(xres*NCSAMP*sizeof(COLORV)); | 
| 412 |  | if (scan == NULL) { | 
| 413 |  | fprintf(stderr, "%s: out of memory\n", progname); | 
| 414 |  | quit(1); | 
| 415 |  | } | 
| 416 |  | for (i = 0; i < yres; i++) { | 
| 417 | < | if (freadscan(scan, xres, in) < 0) { | 
| 417 | > | if (freadsscan(scan, NCSAMP, xres, in) < 0) { | 
| 418 |  | nrows = (long)nrows * i / yres; /* adjust frame */ | 
| 419 |  | if (nrows <= 0) { | 
| 420 |  | fprintf(stderr, "%s: empty frame\n", progname); | 
| 429 |  | } | 
| 430 |  | pass1scan(scan, i); | 
| 431 |  | } | 
| 432 | < | free((void *)scan); | 
| 432 | > | free(scan); | 
| 433 |  | } | 
| 434 |  |  | 
| 435 |  |  | 
| 436 | < | pass2(in)                       /* last pass on file, write to stdout */ | 
| 437 | < | FILE  *in; | 
| 436 | > | static void | 
| 437 | > | pass2(                  /* last pass on file, write to stdout */ | 
| 438 | > | FILE  *in | 
| 439 | > | ) | 
| 440 |  | { | 
| 441 |  | int  yread; | 
| 442 |  | int  ycent, xcent; | 
| 449 |  | ycent = (r+.5)*yres/nrows; | 
| 450 |  | while (yread <= ycent+yrad) { | 
| 451 |  | if (yread < yres) { | 
| 452 | < | if (freadscan(scanin[yread%barsize], | 
| 453 | < | xres, in) < 0) { | 
| 452 | > | if (freadsscan(scanin[yread%barsize], | 
| 453 | > | NCSAMP, xres, in) < 0) { | 
| 454 |  | fprintf(stderr, | 
| 455 |  | "%s: truncated input (y=%d)\n", | 
| 456 |  | progname, yres-1-yread); | 
| 467 |  | if (thresh > FTINY) | 
| 468 |  | dothresh(xcent, ycent, c, r); | 
| 469 |  | else if (rad > FTINY) | 
| 470 | < | dogauss(scanout[c], xcent, ycent, c, r); | 
| 470 | > | dogauss(scanout+c*NCSAMP, xcent, ycent, c, r); | 
| 471 |  | else | 
| 472 | < | dobox(scanout[c], xcent, ycent, c, r); | 
| 472 | > | dobox(scanout+c*NCSAMP, xcent, ycent, c, r); | 
| 473 |  | } | 
| 474 | < | if (scanout != NULL && fwritescan(scanout, ncols, stdout) < 0) { | 
| 474 | > | if (scanout != NULL && fwritesscan(scanout, NCSAMP, ncols, stdout) < 0) { | 
| 475 |  | fprintf(stderr, "%s: write error in pass2\n", progname); | 
| 476 |  | quit(1); | 
| 477 |  | } | 
| 478 |  | } | 
| 479 |  | /* skip leftover input */ | 
| 480 |  | while (yread < yres) { | 
| 481 | < | if (freadscan(scanin[0], xres, in) < 0) | 
| 481 | > | if (freadsscan(scanin[0], NCSAMP, xres, in) < 0) | 
| 482 |  | break; | 
| 483 |  | yread++; | 
| 484 |  | } | 
| 486 |  | } | 
| 487 |  |  | 
| 488 |  |  | 
| 489 | < | scan2init()                     /* prepare scanline arrays */ | 
| 489 | > | static void | 
| 490 | > | scan2init(void)                 /* prepare scanline arrays */ | 
| 491 |  | { | 
| 492 |  | COLOR   ctmp; | 
| 493 |  | double  d; | 
| 494 | < | register int  i; | 
| 494 | > | int  i; | 
| 495 |  |  | 
| 496 |  | xbrad = xres/ncols/2 + 1; | 
| 497 |  | ybrad = yres/nrows/2 + 1; | 
| 514 |  | yrad = ybrad; | 
| 515 |  | } | 
| 516 |  | barsize = 2*yrad + 1; | 
| 517 | < | scanin = (COLOR **)malloc(barsize*sizeof(COLOR *)); | 
| 517 | > | scanin = (COLORV **)malloc(barsize*sizeof(COLORV *)); | 
| 518 |  | if (scanin == NULL) | 
| 519 |  | goto memerr; | 
| 520 |  | for (i = 0; i < barsize; i++) { | 
| 521 | < | scanin[i] = (COLOR *)malloc(xres*sizeof(COLOR)); | 
| 521 | > | scanin[i] = (COLORV *)malloc(xres*NCSAMP*sizeof(COLORV)); | 
| 522 |  | if (scanin[i] == NULL) | 
| 523 |  | goto memerr; | 
| 524 |  | } | 
| 525 |  | if (obarsize > 0) { | 
| 526 | < | scoutbar = (COLOR **)malloc(obarsize*sizeof(COLOR *)); | 
| 526 | > | scoutbar = (COLORV **)malloc(obarsize*sizeof(COLORV *)); | 
| 527 |  | greybar = (float **)malloc(obarsize*sizeof(float *)); | 
| 528 | < | if (scoutbar == NULL | greybar == NULL) | 
| 528 | > | if ((scoutbar == NULL) | (greybar == NULL)) | 
| 529 |  | goto memerr; | 
| 530 |  | for (i = 0; i < obarsize; i++) { | 
| 531 | < | scoutbar[i] = (COLOR *)malloc(ncols*sizeof(COLOR)); | 
| 531 | > | scoutbar[i] = (COLORV *)malloc(ncols*NCSAMP*sizeof(COLORV)); | 
| 532 |  | greybar[i] = (float *)malloc(ncols*sizeof(float)); | 
| 533 | < | if (scoutbar[i] == NULL | greybar[i] == NULL) | 
| 533 | > | if ((scoutbar[i] == NULL) | (greybar[i] == NULL)) | 
| 534 |  | goto memerr; | 
| 535 |  | } | 
| 536 |  | } else { | 
| 537 | < | scanout = (COLOR *)malloc(ncols*sizeof(COLOR)); | 
| 537 | > | scanout = (COLORV *)malloc(ncols*NCSAMP*sizeof(COLORV)); | 
| 538 |  | if (scanout == NULL) | 
| 539 |  | goto memerr; | 
| 540 |  | } | 
| 545 |  | fputaspect(d, stdout); | 
| 546 |  | } | 
| 547 |  | /* record exposure */ | 
| 548 | < | d = (*ourbright)(exposure); | 
| 548 | > | d = bright(exposure); | 
| 549 |  | if (!FEQ(d,1.0)) | 
| 550 |  | fputexpos(d, stdout); | 
| 551 |  | /* record color correction */ | 
| 564 |  | } | 
| 565 |  |  | 
| 566 |  |  | 
| 567 | < | scan2sync(r)                    /* synchronize grey averages and output scan */ | 
| 568 | < | int  r; | 
| 567 | > | static void | 
| 568 | > | scan2sync(                      /* synchronize grey averages and output scan */ | 
| 569 | > | int  r | 
| 570 | > | ) | 
| 571 |  | { | 
| 572 |  | static int  nextrow = 0; | 
| 573 | < | COLOR  ctmp; | 
| 573 | > | SCOLOR  ctmp; | 
| 574 |  | int  ybot; | 
| 575 | < | register int  c; | 
| 575 | > | int  c; | 
| 576 |  | /* average input scanlines */ | 
| 577 |  | while (nextrow <= r+orad && nextrow < nrows) { | 
| 578 |  | ybot = (nextrow+.5)*yres/nrows; | 
| 581 |  | greybar[nextrow%obarsize][c] = (*ourbright)(ctmp); | 
| 582 |  | } | 
| 583 |  | /* and zero output scanline */ | 
| 584 | < | bzero((char *)scoutbar[nextrow%obarsize], ncols*sizeof(COLOR)); | 
| 584 | > | memset(scoutbar[nextrow%obarsize], 0, ncols*NCSAMP*sizeof(COLORV)); | 
| 585 |  | nextrow++; | 
| 586 |  | } | 
| 587 |  | /* point to top scanline for output */ | 
| 592 |  | } | 
| 593 |  |  | 
| 594 |  |  | 
| 595 | < | scan2flush()                    /* flush output buffer */ | 
| 595 | > | static void | 
| 596 | > | scan2flush(void)                        /* flush output buffer */ | 
| 597 |  | { | 
| 598 | < | register int  r; | 
| 598 | > | int  r; | 
| 599 |  |  | 
| 600 |  | for (r = nrows-orad; r < nrows; r++) | 
| 601 | < | if (fwritescan(scoutbar[r%obarsize], ncols, stdout) < 0) | 
| 601 | > | if (fwritesscan(scoutbar[r%obarsize], NCSAMP, ncols, stdout) < 0) | 
| 602 |  | break; | 
| 603 |  | if (fflush(stdout) < 0) { | 
| 604 |  | fprintf(stderr, "%s: write error at end of pass2\n", progname); |