| 1 | < | /* Copyright (c) 1986 Regents of the University of California */ | 
| 1 | > | /* Copyright (c) 1996 Regents of the University of California */ | 
| 2 |  |  | 
| 3 |  | #ifndef lint | 
| 4 |  | static char SCCSid[] = "$SunId$ LBL"; | 
| 8 |  | *  pfilt.c - program to post-process picture file. | 
| 9 |  | * | 
| 10 |  | *     9/26/85 | 
| 11 | + | *     6/23/93  Added additional buffers for value spreading | 
| 12 |  | */ | 
| 13 |  |  | 
| 14 | < | #include  <stdio.h> | 
| 14 | > | #include  "standard.h" | 
| 15 |  |  | 
| 16 |  | #include  <signal.h> | 
| 17 |  |  | 
| 18 |  | #include  "color.h" | 
| 19 |  |  | 
| 20 | < | extern char  *malloc(); | 
| 20 | > | #include  "resolu.h" | 
| 21 | > |  | 
| 22 | > | #include  "paths.h" | 
| 23 | > |  | 
| 24 |  | extern float  *matchlamp(); | 
| 25 |  |  | 
| 26 | < | #define  FEQ(a,b)       ((a) >= .98*(b) && (a) <= 1.02*(b)) | 
| 26 | > | #define  FEQ(a,b)       ((a) >= .98*(b) && (a) <= 1.02*(b)) | 
| 27 |  |  | 
| 28 | < | #define  CHECKRAD       1.5     /* radius to check for filtering */ | 
| 28 | > | double   CHECKRAD = 1.5;        /* radius to check for filtering */ | 
| 29 |  |  | 
| 30 | + | #define  THRESHRAD      5.0     /* maximum sample spread in output */ | 
| 31 | + |  | 
| 32 |  | COLOR  exposure = WHTCOLOR;     /* exposure for the frame */ | 
| 33 |  |  | 
| 34 | < | double  rad = 0.0;              /* output pixel radius for filtering */ | 
| 34 | > | double  rad = 0.0;              /* output pixel radius for filtering */ | 
| 35 |  |  | 
| 36 | + | double  thresh = 0.0;           /* maximum contribution for subpixel */ | 
| 37 | + |  | 
| 38 |  | int  nrows = 0;                 /* number of rows for output */ | 
| 39 |  | int  ncols = 0;                 /* number of columns for output */ | 
| 40 |  |  | 
| 41 | < | double  x_c = 1.0;              /* ratio of output x size to input */ | 
| 42 | < | double  y_r = 1.0;              /* ratio of output y size to input */ | 
| 41 | > | double  x_c = 1.0;              /* ratio of output x size to input */ | 
| 42 | > | double  y_r = 1.0;              /* ratio of output y size to input */ | 
| 43 |  |  | 
| 44 |  | int  singlepass = 0;            /* true means skip first pass */ | 
| 45 |  |  | 
| 46 |  | int  avghot = 0;                /* true means average in bright spots */ | 
| 47 |  |  | 
| 48 | < | double  hotlvl = 1000.0;        /* level considered "hot" */ | 
| 48 | > | double  hotlvl = 100.0;         /* level considered "hot" */ | 
| 49 |  |  | 
| 50 |  | int  npts = 0;                  /* (half) number of points for stars */ | 
| 51 |  |  | 
| 52 | < | double  spread = 1e-4;          /* spread for star points */ | 
| 52 | > | double  spread = 1e-4;          /* spread for star points */ | 
| 53 |  |  | 
| 46 | – | #define  TEMPLATE       "/usr/tmp/pfXXXXXX" | 
| 47 | – |  | 
| 54 |  | char  *tfname = NULL; | 
| 55 |  |  | 
| 56 | + | char  template[] = TEMPLATE; | 
| 57 | + |  | 
| 58 |  | char  *lampdat = "lamp.tab";    /* lamp data file */ | 
| 59 |  |  | 
| 60 | + | int  order;                     /* scanline ordering of input */ | 
| 61 |  | int  xres, yres;                /* resolution of input */ | 
| 62 | < | double  inpaspect = 1.0;        /* pixel aspect ratio of input */ | 
| 62 | > | double  inpaspect = 1.0;        /* pixel aspect ratio of input */ | 
| 63 |  | int  correctaspect = 0;         /* aspect ratio correction? */ | 
| 64 |  |  | 
| 65 |  | int  wrongformat = 0; | 
| 66 |  |  | 
| 67 | < | int  xrad;                      /* x window size */ | 
| 68 | < | int  yrad;                      /* y window size */ | 
| 67 | > | int  xrad;                      /* x search radius */ | 
| 68 | > | int  yrad;                      /* y search radius */ | 
| 69 | > | int  xbrad;                     /* x box size */ | 
| 70 | > | int  ybrad;                     /* y box size */ | 
| 71 |  |  | 
| 72 |  | int  barsize;                   /* size of input scan bar */ | 
| 73 |  | COLOR  **scanin;                /* input scan bar */ | 
| 74 |  | COLOR  *scanout;                /* output scan line */ | 
| 75 | + | COLOR  **scoutbar;              /* output scan bar (if thresh > 0) */ | 
| 76 | + | float  **greybar;               /* grey-averaged input values */ | 
| 77 | + | int  obarsize = 0;              /* size of output scan bar */ | 
| 78 | + | int  orad = 0;                  /* output window radius */ | 
| 79 |  |  | 
| 80 |  | char  *progname; | 
| 81 |  |  | 
| 84 |  | int  argc; | 
| 85 |  | char  **argv; | 
| 86 |  | { | 
| 72 | – | extern char  *mktemp(); | 
| 73 | – | extern double  atof(), pow(); | 
| 87 |  | extern long  ftell(); | 
| 88 |  | extern int  quit(), headline(); | 
| 89 |  | FILE  *fin; | 
| 90 |  | float  *lampcolor; | 
| 91 |  | char  *lamptype = NULL; | 
| 92 |  | long  fpos; | 
| 93 | < | double  outaspect = 0.0; | 
| 94 | < | double  d; | 
| 95 | < | int  i; | 
| 96 | < |  | 
| 93 | > | double  outaspect = 0.0; | 
| 94 | > | double  d; | 
| 95 | > | int  i, j; | 
| 96 | > | #ifdef MSDOS | 
| 97 | > | extern int  _fmode; | 
| 98 | > | _fmode = O_BINARY; | 
| 99 | > | setmode(fileno(stdin), O_BINARY); | 
| 100 | > | setmode(fileno(stdout), O_BINARY); | 
| 101 | > | #endif | 
| 102 |  | if (signal(SIGINT, quit) == SIG_IGN) | 
| 103 |  | signal(SIGINT, SIG_IGN); | 
| 104 |  | if (signal(SIGHUP, quit) == SIG_IGN) | 
| 105 | < | signal(SIGINT, SIG_IGN); | 
| 105 | > | signal(SIGHUP, SIG_IGN); | 
| 106 |  | signal(SIGTERM, quit); | 
| 107 |  | signal(SIGPIPE, quit); | 
| 108 | < | #ifdef  SIGXCPU | 
| 108 | > | #ifdef  SIGXCPU | 
| 109 |  | signal(SIGXCPU, quit); | 
| 110 |  | signal(SIGXFSZ, quit); | 
| 111 |  | #endif | 
| 112 |  |  | 
| 113 | < | progname = argv[0]; | 
| 113 | > | progname = argv[0] = fixargv0(argv[0]); | 
| 114 |  |  | 
| 115 |  | for (i = 1; i < argc; i++) | 
| 116 |  | if (argv[i][0] == '-') | 
| 194 |  | case 'r': | 
| 195 |  | rad = atof(argv[++i]); | 
| 196 |  | break; | 
| 197 | + | case 'm': | 
| 198 | + | thresh = atof(argv[++i]); | 
| 199 | + | if (rad <= FTINY) | 
| 200 | + | rad = 1.0; | 
| 201 | + | break; | 
| 202 |  | case 'b': | 
| 203 | < | rad = 0.0; | 
| 203 | > | rad = thresh = 0.0; | 
| 204 |  | break; | 
| 205 |  | default:; | 
| 206 |  | badopt: | 
| 219 |  | fprintf(stderr, "%s: unknown lamp type\n", lamptype); | 
| 220 |  | quit(1); | 
| 221 |  | } | 
| 222 | < | colval(exposure,RED) /= lampcolor[0]; | 
| 223 | < | colval(exposure,GRN) /= lampcolor[1]; | 
| 224 | < | colval(exposure,BLU) /= lampcolor[2]; | 
| 222 | > | for (j = 0; j < 3; j++) | 
| 223 | > | if (lampcolor[j] > 1e-4) | 
| 224 | > | colval(exposure,j) /= lampcolor[j]; | 
| 225 |  | freelamps(); | 
| 226 |  | } | 
| 227 |  | /* open input file */ | 
| 229 |  | if (singlepass) | 
| 230 |  | fin = stdin; | 
| 231 |  | else { | 
| 232 | < | tfname = mktemp(TEMPLATE); | 
| 232 | > | tfname = mktemp(template); | 
| 233 |  | if ((fin = fopen(tfname, "w+")) == NULL) { | 
| 234 |  | fprintf(stderr, "%s: can't create ", progname); | 
| 235 |  | fprintf(stderr, "temp file \"%s\"\n", tfname); | 
| 261 |  | /* add new header info. */ | 
| 262 |  | printargs(i, argv, stdout); | 
| 263 |  | /* get picture size */ | 
| 264 | < | if (fgetresolu(&xres, &yres, fin) != (YMAJOR|YDECR)) { | 
| 264 | > | if ((order = fgetresolu(&xres, &yres, fin)) < 0) { | 
| 265 |  | fprintf(stderr, "%s: bad picture size\n", progname); | 
| 266 |  | quit(1); | 
| 267 |  | } | 
| 268 | + | if (!(order & YMAJOR)) | 
| 269 | + | inpaspect = 1.0/inpaspect; | 
| 270 |  | /* compute output resolution */ | 
| 271 |  | if (ncols <= 0) | 
| 272 |  | ncols = x_c*xres + .5; | 
| 302 |  | } | 
| 303 |  |  | 
| 304 |  |  | 
| 305 | + | double | 
| 306 | + | rgb_bright(clr) | 
| 307 | + | COLOR  clr; | 
| 308 | + | { | 
| 309 | + | return(bright(clr)); | 
| 310 | + | } | 
| 311 | + |  | 
| 312 | + |  | 
| 313 | + | double | 
| 314 | + | xyz_bright(clr) | 
| 315 | + | COLOR  clr; | 
| 316 | + | { | 
| 317 | + | return(clr[CIEY]); | 
| 318 | + | } | 
| 319 | + |  | 
| 320 | + |  | 
| 321 | + | double  (*ourbright)() = rgb_bright; | 
| 322 | + |  | 
| 323 | + |  | 
| 324 |  | headline(s)                             /* process line from header */ | 
| 325 |  | char  *s; | 
| 326 |  | { | 
| 329 |  | fputs(s, stdout);               /* copy to output */ | 
| 330 |  | if (isaspect(s))                /* get aspect ratio */ | 
| 331 |  | inpaspect *= aspectval(s); | 
| 332 | < | else if (isformat(s)) { | 
| 333 | < | formatval(fmt, s); | 
| 334 | < | wrongformat = strcmp(fmt, COLRFMT); | 
| 332 | > | else if (isexpos(s))            /* get exposure */ | 
| 333 | > | hotlvl *= exposval(s); | 
| 334 | > | else if (formatval(fmt, s)) {   /* get format */ | 
| 335 | > | wrongformat = 0; | 
| 336 | > | if (!strcmp(COLRFMT, fmt)) | 
| 337 | > | ourbright = rgb_bright; | 
| 338 | > | else if (!strcmp(CIEFMT, fmt)) | 
| 339 | > | ourbright = xyz_bright; | 
| 340 | > | else | 
| 341 | > | wrongformat = !globmatch(PICFMT, fmt); | 
| 342 |  | } | 
| 343 |  | } | 
| 344 |  |  | 
| 373 |  | } | 
| 374 |  | for (i = 0; i < yres; i++) { | 
| 375 |  | if (freadscan(scan, xres, in) < 0) { | 
| 376 | < | nrows = nrows * i / yres;       /* adjust frame */ | 
| 376 | > | nrows = (long)nrows * i / yres; /* adjust frame */ | 
| 377 |  | if (nrows <= 0) { | 
| 378 |  | fprintf(stderr, "%s: empty frame\n", progname); | 
| 379 |  | quit(1); | 
| 380 |  | } | 
| 381 |  | fprintf(stderr, "%s: warning - partial frame (%d%%)\n", | 
| 382 | < | progname, 100*i/yres); | 
| 382 | > | progname, (int)(100L*i/yres)); | 
| 383 |  | yres = i; | 
| 384 |  | y_r = (double)nrows/yres; | 
| 385 |  | break; | 
| 396 |  | int  yread; | 
| 397 |  | int  ycent, xcent; | 
| 398 |  | int  r, c; | 
| 399 | < |  | 
| 399 | > |  | 
| 400 |  | pass2init(); | 
| 401 |  | scan2init(); | 
| 402 |  | yread = 0; | 
| 407 |  | if (freadscan(scanin[yread%barsize], | 
| 408 |  | xres, in) < 0) { | 
| 409 |  | fprintf(stderr, | 
| 410 | < | "%s: bad read (y=%d)\n", | 
| 410 | > | "%s: truncated input (y=%d)\n", | 
| 411 |  | progname, yres-1-yread); | 
| 412 |  | quit(1); | 
| 413 |  | } | 
| 415 |  | } | 
| 416 |  | yread++; | 
| 417 |  | } | 
| 418 | + | if (obarsize > 0) | 
| 419 | + | scan2sync(r); | 
| 420 |  | for (c = 0; c < ncols; c++) { | 
| 421 |  | xcent = (long)c*xres/ncols; | 
| 422 | < | if (rad <= 0.0) | 
| 423 | < | dobox(scanout[c], xcent, ycent, c, r); | 
| 424 | < | else | 
| 422 | > | if (thresh > FTINY) | 
| 423 | > | dothresh(xcent, ycent, c, r); | 
| 424 | > | else if (rad > FTINY) | 
| 425 |  | dogauss(scanout[c], xcent, ycent, c, r); | 
| 426 | + | else | 
| 427 | + | dobox(scanout[c], xcent, ycent, c, r); | 
| 428 |  | } | 
| 429 | < | if (fwritescan(scanout, ncols, stdout) < 0) { | 
| 429 | > | if (scanout != NULL && fwritescan(scanout, ncols, stdout) < 0) { | 
| 430 |  | fprintf(stderr, "%s: write error in pass2\n", progname); | 
| 431 |  | quit(1); | 
| 432 |  | } | 
| 433 |  | } | 
| 434 | < | /* skip leftovers */ | 
| 434 | > | /* skip leftover input */ | 
| 435 |  | while (yread < yres) { | 
| 436 |  | if (freadscan(scanin[0], xres, in) < 0) | 
| 437 |  | break; | 
| 438 |  | yread++; | 
| 439 |  | } | 
| 440 | + | scan2flush();                   /* flush output */ | 
| 441 |  | } | 
| 442 |  |  | 
| 443 |  |  | 
| 444 |  | scan2init()                     /* prepare scanline arrays */ | 
| 445 |  | { | 
| 446 |  | COLOR   ctmp; | 
| 447 | < | double  d; | 
| 447 | > | double  d; | 
| 448 |  | register int  i; | 
| 449 |  |  | 
| 450 | < | if (rad <= 0.0) { | 
| 451 | < | xrad = xres/ncols/2 + 1; | 
| 452 | < | yrad = yres/nrows/2 + 1; | 
| 397 | < | } else { | 
| 450 | > | xbrad = xres/ncols/2 + 1; | 
| 451 | > | ybrad = yres/nrows/2 + 1; | 
| 452 | > | if (rad > FTINY) { | 
| 453 |  | if (nrows >= yres && ncols >= xres) | 
| 454 |  | rad *= (y_r + x_c)/2.0; | 
| 455 |  |  | 
| 456 | < | xrad = CHECKRAD*rad/x_c + 1; | 
| 457 | < | yrad = CHECKRAD*rad/y_r + 1; | 
| 458 | < |  | 
| 456 | > | if (thresh > FTINY) { | 
| 457 | > | orad = CHECKRAD*THRESHRAD*rad + 1; | 
| 458 | > | xrad = orad/x_c + xbrad; | 
| 459 | > | yrad = orad/y_r + ybrad; | 
| 460 | > | obarsize = 2*orad + 1; | 
| 461 | > | } else { | 
| 462 | > | xrad = CHECKRAD*rad/x_c + 1; | 
| 463 | > | yrad = CHECKRAD*rad/y_r + 1; | 
| 464 | > | } | 
| 465 |  | initmask();             /* initialize filter table */ | 
| 466 | + | } else { | 
| 467 | + | xrad = xbrad; | 
| 468 | + | yrad = ybrad; | 
| 469 |  | } | 
| 470 | < | barsize = 2 * yrad; | 
| 470 | > | barsize = 2*yrad + 1; | 
| 471 |  | scanin = (COLOR **)malloc(barsize*sizeof(COLOR *)); | 
| 472 | + | if (scanin == NULL) | 
| 473 | + | goto memerr; | 
| 474 |  | for (i = 0; i < barsize; i++) { | 
| 475 |  | scanin[i] = (COLOR *)malloc(xres*sizeof(COLOR)); | 
| 476 | < | if (scanin[i] == NULL) { | 
| 477 | < | fprintf(stderr, "%s: out of memory\n", progname); | 
| 478 | < | quit(1); | 
| 476 | > | if (scanin[i] == NULL) | 
| 477 | > | goto memerr; | 
| 478 | > | } | 
| 479 | > | if (obarsize > 0) { | 
| 480 | > | scoutbar = (COLOR **)malloc(obarsize*sizeof(COLOR *)); | 
| 481 | > | greybar = (float **)malloc(obarsize*sizeof(float *)); | 
| 482 | > | if (scoutbar == NULL | greybar == NULL) | 
| 483 | > | goto memerr; | 
| 484 | > | for (i = 0; i < obarsize; i++) { | 
| 485 | > | scoutbar[i] = (COLOR *)malloc(ncols*sizeof(COLOR)); | 
| 486 | > | greybar[i] = (float *)malloc(ncols*sizeof(float)); | 
| 487 | > | if (scoutbar[i] == NULL | greybar[i] == NULL) | 
| 488 | > | goto memerr; | 
| 489 |  | } | 
| 490 | + | } else { | 
| 491 | + | scanout = (COLOR *)malloc(ncols*sizeof(COLOR)); | 
| 492 | + | if (scanout == NULL) | 
| 493 | + | goto memerr; | 
| 494 |  | } | 
| 415 | – | scanout = (COLOR *)malloc(ncols*sizeof(COLOR)); | 
| 416 | – | if (scanout == NULL) { | 
| 417 | – | fprintf(stderr, "%s: out of memory\n", progname); | 
| 418 | – | quit(1); | 
| 419 | – | } | 
| 495 |  | /* record pixel aspect ratio */ | 
| 496 |  | if (!correctaspect) { | 
| 497 | < | d = x_c / y_r; | 
| 497 | > | d = order & YMAJOR ? x_c/y_r : y_r/x_c ; | 
| 498 |  | if (!FEQ(d,1.0)) | 
| 499 |  | fputaspect(d, stdout); | 
| 500 |  | } | 
| 501 |  | /* record exposure */ | 
| 502 | < | d = bright(exposure); | 
| 502 | > | d = (*ourbright)(exposure); | 
| 503 |  | if (!FEQ(d,1.0)) | 
| 504 |  | fputexpos(d, stdout); | 
| 505 |  | /* record color correction */ | 
| 510 |  | fputcolcor(ctmp, stdout); | 
| 511 |  | printf("\n"); | 
| 512 |  | /* write out resolution */ | 
| 513 | < | fputresolu(YMAJOR|YDECR, ncols, nrows, stdout); | 
| 513 | > | fputresolu(order, ncols, nrows, stdout); | 
| 514 | > | return; | 
| 515 | > | memerr: | 
| 516 | > | fprintf(stderr, "%s: out of memory\n", progname); | 
| 517 | > | quit(1); | 
| 518 | > | } | 
| 519 | > |  | 
| 520 | > |  | 
| 521 | > | scan2sync(r)                    /* synchronize grey averages and output scan */ | 
| 522 | > | int  r; | 
| 523 | > | { | 
| 524 | > | static int  nextrow = 0; | 
| 525 | > | COLOR  ctmp; | 
| 526 | > | int  ybot; | 
| 527 | > | register int  c; | 
| 528 | > | /* average input scanlines */ | 
| 529 | > | while (nextrow <= r+orad && nextrow < nrows) { | 
| 530 | > | ybot = (long)nextrow*yres/nrows; | 
| 531 | > | for (c = 0; c < ncols; c++) { | 
| 532 | > | dobox(ctmp, (int)((long)c*xres/ncols),ybot, c,nextrow); | 
| 533 | > | greybar[nextrow%obarsize][c] = (*ourbright)(ctmp); | 
| 534 | > | } | 
| 535 | > | /* and zero output scanline */ | 
| 536 | > | bzero((char *)scoutbar[nextrow%obarsize], ncols*sizeof(COLOR)); | 
| 537 | > | nextrow++; | 
| 538 | > | } | 
| 539 | > | /* point to top scanline for output */ | 
| 540 | > | if (r-orad >= 0) | 
| 541 | > | scanout = scoutbar[(r-orad)%obarsize]; | 
| 542 | > | else | 
| 543 | > | scanout = NULL; | 
| 544 | > | } | 
| 545 | > |  | 
| 546 | > |  | 
| 547 | > | scan2flush()                    /* flush output buffer */ | 
| 548 | > | { | 
| 549 | > | register int  r; | 
| 550 | > |  | 
| 551 | > | for (r = nrows-orad; r < nrows; r++) | 
| 552 | > | if (fwritescan(scoutbar[r%obarsize], ncols, stdout) < 0) | 
| 553 | > | break; | 
| 554 | > | if (fflush(stdout) < 0) { | 
| 555 | > | fprintf(stderr, "%s: write error at end of pass2\n", progname); | 
| 556 | > | exit(1); | 
| 557 | > | } | 
| 558 |  | } | 
| 559 |  |  | 
| 560 |  |  |