| 1 | < | /* Copyright (c) 1990 Regents of the University of California */ | 
| 1 | > | /* Copyright (c) 1991 Regents of the University of California */ | 
| 2 |  |  | 
| 3 |  | #ifndef lint | 
| 4 |  | static char SCCSid[] = "$SunId$ LBL"; | 
| 30 |  | #include  "pic.h" | 
| 31 |  | #include  "x11raster.h" | 
| 32 |  | #include  "random.h" | 
| 33 | + | #include  "resolu.h" | 
| 34 |  |  | 
| 35 |  | #define  FONTNAME       "8x13"          /* text font we'll use */ | 
| 36 |  |  | 
| 37 | < | #define  CTRL(c)        ('c'-'@') | 
| 37 | > | #define  CTRL(c)        ((c)-'@') | 
| 38 |  |  | 
| 39 |  | #define  BORWIDTH       5               /* border width */ | 
| 40 |  |  | 
| 41 | + | #define  ICONSIZ        (8*10)          /* maximum icon dimension (even 8) */ | 
| 42 | + |  | 
| 43 |  | #define  ourscreen      DefaultScreen(thedisplay) | 
| 44 |  | #define  ourblack       BlackPixel(thedisplay,ourscreen) | 
| 45 |  | #define  ourwhite       WhitePixel(thedisplay,ourscreen) | 
| 71 |  |  | 
| 72 |  | COLR  *scanline;                        /* scan line buffer */ | 
| 73 |  |  | 
| 74 | < | int  xmax, ymax;                        /* picture resolution */ | 
| 74 | > | RESOLU  inpres;                         /* input resolution and ordering */ | 
| 75 | > | int  xmax, ymax;                        /* picture dimensions */ | 
| 76 |  | int  width, height;                     /* window size */ | 
| 77 |  | char  *fname = NULL;                    /* input file name */ | 
| 78 |  | FILE  *fin = stdin;                     /* input file */ | 
| 81 |  |  | 
| 82 |  | double  exposure = 1.0;                 /* exposure compensation used */ | 
| 83 |  |  | 
| 84 | + | int  wrongformat = 0;                   /* input in another format? */ | 
| 85 | + |  | 
| 86 |  | GC      revgc;                          /* graphics context with GXinvert */ | 
| 87 |  |  | 
| 88 |  | XRASTER *ourras;                        /* our stored image */ | 
| 94 |  |  | 
| 95 |  | char  *geometry = NULL;                 /* geometry specification */ | 
| 96 |  |  | 
| 97 | + | char  icondata[ICONSIZ*ICONSIZ/8];      /* icon bitmap data */ | 
| 98 | + | int  iconwidth = 0, iconheight = 0; | 
| 99 | + |  | 
| 100 |  | char  *progname; | 
| 101 |  |  | 
| 102 |  | char  errmsg[128]; | 
| 105 |  |  | 
| 106 |  | extern char  *malloc(), *calloc(); | 
| 107 |  |  | 
| 108 | < | extern double  atof(), pow(), log(); | 
| 108 | > | extern double  pow(), log(); | 
| 109 |  |  | 
| 110 |  | Display  *thedisplay; | 
| 111 |  |  | 
| 165 |  | } else if (i != argc) | 
| 166 |  | goto userr; | 
| 167 |  | /* get header */ | 
| 168 | < | getheader(fin, headline); | 
| 168 | > | getheader(fin, headline, NULL); | 
| 169 |  | /* get picture dimensions */ | 
| 170 | < | if (fgetresolu(&xmax, &ymax, fin) != (YMAJOR|YDECR)) | 
| 171 | < | quiterr("bad picture size"); | 
| 170 | > | if (wrongformat || !fgetsresolu(&inpres, fin)) | 
| 171 | > | quiterr("bad picture format"); | 
| 172 | > | xmax = scanlen(&inpres); | 
| 173 | > | ymax = numscans(&inpres); | 
| 174 |  | /* set view parameters */ | 
| 175 |  | if (gotview && setview(&ourview) != NULL) | 
| 176 |  | gotview = 0; | 
| 192 |  | headline(s)             /* get relevant info from header */ | 
| 193 |  | char  *s; | 
| 194 |  | { | 
| 195 | < | static char  *altname[] = {"rview","rpict","pinterp",VIEWSTR,NULL}; | 
| 185 | < | register char  **an; | 
| 195 | > | char  fmt[32]; | 
| 196 |  |  | 
| 197 |  | if (isexpos(s)) | 
| 198 |  | exposure *= exposval(s); | 
| 199 | < | else | 
| 200 | < | for (an = altname; *an != NULL; an++) | 
| 201 | < | if (!strncmp(*an, s, strlen(*an))) { | 
| 202 | < | if (sscanview(&ourview, s+strlen(*an)) > 0) | 
| 203 | < | gotview++; | 
| 194 | < | return; | 
| 195 | < | } | 
| 199 | > | else if (isformat(s)) { | 
| 200 | > | formatval(fmt, s); | 
| 201 | > | wrongformat = strcmp(fmt, COLRFMT); | 
| 202 | > | } else if (isview(s) && sscanview(&ourview, s) > 0) | 
| 203 | > | gotview++; | 
| 204 |  | } | 
| 205 |  |  | 
| 206 |  |  | 
| 207 |  | init()                  /* get data and open window */ | 
| 208 |  | { | 
| 209 | + | XWMHints        ourxwmhints; | 
| 210 |  | XSetWindowAttributes    ourwinattr; | 
| 211 |  | XSizeHints  oursizhints; | 
| 212 |  | register int  i; | 
| 243 |  | XSetFont(thedisplay, ourgc, fontid); | 
| 244 |  | revgc = XCreateGC(thedisplay, wind, 0, 0); | 
| 245 |  | XSetFunction(thedisplay, revgc, GXinvert); | 
| 237 | – | XStoreName(thedisplay, wind, fname == NULL ? progname : fname); | 
| 246 |  | XDefineCursor(thedisplay, wind, XCreateFontCursor(thedisplay, | 
| 247 |  | XC_diamond_cross)); | 
| 248 | + | XStoreName(thedisplay, wind, fname == NULL ? progname : fname); | 
| 249 |  | if (geometry != NULL) { | 
| 250 |  | bzero((char *)&oursizhints, sizeof(oursizhints)); | 
| 251 |  | i = XParseGeometry(geometry, &oursizhints.x, &oursizhints.y, | 
| 269 |  | } | 
| 270 |  | XSetNormalHints(thedisplay, wind, &oursizhints); | 
| 271 |  | } | 
| 272 | + | ourxwmhints.flags = InputHint|IconPixmapHint; | 
| 273 | + | ourxwmhints.input = True; | 
| 274 | + | ourxwmhints.icon_pixmap = XCreateBitmapFromData(thedisplay, | 
| 275 | + | wind, icondata, iconwidth, iconheight); | 
| 276 | + | XSetWMHints(thedisplay, wind, &ourxwmhints); | 
| 277 |  | XSelectInput(thedisplay, wind, ButtonPressMask|ButtonReleaseMask | 
| 278 |  | |ButtonMotionMask|StructureNotifyMask | 
| 279 |  | |KeyPressMask|ExposureMask); | 
| 403 |  | XColor  cvx; | 
| 404 |  | int  com, n; | 
| 405 |  | double  comp; | 
| 406 | + | FLOAT  hv[2]; | 
| 407 |  | FVECT  rorg, rdir; | 
| 408 |  |  | 
| 409 |  | n = XLookupString(ekey, buf, sizeof(buf), NULL, NULL); | 
| 412 |  | com = buf[0]; | 
| 413 |  | switch (com) {                  /* interpret command */ | 
| 414 |  | case 'q': | 
| 415 | < | case CTRL(D):                           /* quit */ | 
| 415 | > | case CTRL('D'):                         /* quit */ | 
| 416 |  | quit(0); | 
| 417 |  | case '\n': | 
| 418 |  | case '\r': | 
| 426 |  | sprintf(buf, "%.3f", intens(cval)/exposure); | 
| 427 |  | break; | 
| 428 |  | case 'l':                               /* luminance */ | 
| 429 | < | sprintf(buf, "%.0fn", bright(cval)*683.0/exposure); | 
| 429 | > | sprintf(buf, "%.0fL", luminance(cval)/exposure); | 
| 430 |  | break; | 
| 431 |  | case 'c':                               /* color */ | 
| 432 |  | comp = pow(2.0, (double)scale); | 
| 452 |  | XStoreColor(thedisplay, ourras->cmap, &cvx); | 
| 453 |  | return(0); | 
| 454 |  | case 'p':                               /* position */ | 
| 455 | < | sprintf(buf, "(%d,%d)", ekey->x-xoff, ymax-1-ekey->y+yoff); | 
| 455 | > | pix2loc(hv, &inpres, ekey->x-xoff, ekey->y-yoff); | 
| 456 | > | sprintf(buf, "(%d,%d)", (int)(hv[0]*inpres.xr), | 
| 457 | > | (int)(hv[1]*inpres.yr)); | 
| 458 |  | XDrawImageString(thedisplay, wind, ourgc, ekey->x, ekey->y, | 
| 459 |  | buf, strlen(buf)); | 
| 460 |  | return(0); | 
| 463 |  | XBell(thedisplay, 0); | 
| 464 |  | return(-1); | 
| 465 |  | } | 
| 466 | < | if (viewray(rorg, rdir, &ourview, | 
| 467 | < | (ekey->x-xoff+.5)/xmax, | 
| 451 | < | (ymax-1-ekey->y+yoff+.5)/ymax) < 0) | 
| 466 | > | pix2loc(hv, &inpres, ekey->x-xoff, ekey->y-yoff); | 
| 467 | > | if (viewray(rorg, rdir, &ourview, hv[0], hv[1]) < 0) | 
| 468 |  | return(-1); | 
| 469 |  | printf("%e %e %e ", rorg[0], rorg[1], rorg[2]); | 
| 470 |  | printf("%e %e %e\n", rdir[0], rdir[1], rdir[2]); | 
| 486 |  | free_raster(ourras); | 
| 487 |  | getras(); | 
| 488 |  | /* fall through */ | 
| 489 | < | case CTRL(R):                           /* redraw */ | 
| 490 | < | case CTRL(L): | 
| 489 | > | case CTRL('R'):                         /* redraw */ | 
| 490 | > | case CTRL('L'): | 
| 491 |  | unmap_rcolors(ourras); | 
| 492 |  | XClearWindow(thedisplay, wind); | 
| 493 |  | map_rcolors(ourras, wind); | 
| 579 |  | avgbox(clr)                             /* average color over current box */ | 
| 580 |  | COLOR  clr; | 
| 581 |  | { | 
| 582 | + | static COLOR  lc; | 
| 583 | + | static int  ll, lr, lt, lb; | 
| 584 |  | int  left, right, top, bottom; | 
| 585 |  | int  y; | 
| 586 |  | double  d; | 
| 604 |  | bottom = ymax; | 
| 605 |  | if (top >= bottom) | 
| 606 |  | return(-1); | 
| 607 | + | if (left == ll && right == lr && top == lt && bottom == lb) { | 
| 608 | + | copycolor(clr, lc); | 
| 609 | + | return; | 
| 610 | + | } | 
| 611 |  | for (y = top; y < bottom; y++) { | 
| 612 |  | if (getscan(y) == -1) | 
| 613 |  | return(-1); | 
| 618 |  | } | 
| 619 |  | d = 1.0/((right-left)*(bottom-top)); | 
| 620 |  | scalecolor(clr, d); | 
| 621 | + | ll = left; lr = right; lt = top; lb = bottom; | 
| 622 | + | copycolor(lc, clr); | 
| 623 |  | return(0); | 
| 624 |  | } | 
| 625 |  |  | 
| 628 |  | { | 
| 629 |  | register unsigned char  *dp; | 
| 630 |  | register int    x, err; | 
| 631 | < | int     y; | 
| 631 | > | int     y, errp; | 
| 632 |  | short   *cerr; | 
| 633 |  |  | 
| 634 |  | if ((cerr = (short *)calloc(xmax,sizeof(short))) == NULL) | 
| 638 |  | if (getscan(y) < 0) | 
| 639 |  | quiterr("seek error in getmono"); | 
| 640 |  | normcolrs(scanline, xmax, scale); | 
| 641 | + | add2icon(y, scanline); | 
| 642 |  | err = 0; | 
| 643 |  | for (x = 0; x < xmax; x++) { | 
| 644 |  | if (!(x&7)) | 
| 645 |  | *++dp = 0; | 
| 646 | + | errp = err; | 
| 647 |  | err += normbright(scanline[x]) + cerr[x]; | 
| 648 |  | if (err > 127) | 
| 649 |  | err -= 255; | 
| 650 |  | else | 
| 651 |  | *dp |= 1<<(7-(x&07)); | 
| 652 | < | cerr[x] = err >>= 1; | 
| 652 | > | err /= 3; | 
| 653 | > | cerr[x] = err + errp; | 
| 654 |  | } | 
| 655 |  | } | 
| 656 |  | free((char *)cerr); | 
| 657 |  | } | 
| 658 |  |  | 
| 659 |  |  | 
| 660 | + | add2icon(y, scan)               /* add a scanline to our icon data */ | 
| 661 | + | int  y; | 
| 662 | + | COLR  *scan; | 
| 663 | + | { | 
| 664 | + | static short  cerr[ICONSIZ]; | 
| 665 | + | static int  ynext; | 
| 666 | + | static char  *dp; | 
| 667 | + | register int  err; | 
| 668 | + | register int    x, ti; | 
| 669 | + | int  errp; | 
| 670 | + |  | 
| 671 | + | if (iconheight == 0) {          /* initialize */ | 
| 672 | + | if (xmax <= ICONSIZ && ymax <= ICONSIZ) { | 
| 673 | + | iconwidth = xmax; | 
| 674 | + | iconheight = ymax; | 
| 675 | + | } else if (xmax > ymax) { | 
| 676 | + | iconwidth = ICONSIZ; | 
| 677 | + | iconheight = ICONSIZ*ymax/xmax; | 
| 678 | + | if (iconheight < 1) | 
| 679 | + | iconheight = 1; | 
| 680 | + | } else { | 
| 681 | + | iconwidth = ICONSIZ*xmax/ymax; | 
| 682 | + | if (iconwidth < 1) | 
| 683 | + | iconwidth = 1; | 
| 684 | + | iconheight = ICONSIZ; | 
| 685 | + | } | 
| 686 | + | ynext = 0; | 
| 687 | + | dp = icondata - 1; | 
| 688 | + | } | 
| 689 | + | if (y < ynext*ymax/iconheight)  /* skip this one */ | 
| 690 | + | return; | 
| 691 | + | err = 0; | 
| 692 | + | for (x = 0; x < iconwidth; x++) { | 
| 693 | + | if (!(x&7)) | 
| 694 | + | *++dp = 0; | 
| 695 | + | errp = err; | 
| 696 | + | ti = x*xmax/iconwidth; | 
| 697 | + | err += normbright(scan[ti]) + cerr[x]; | 
| 698 | + | if (err > 127) | 
| 699 | + | err -= 255; | 
| 700 | + | else | 
| 701 | + | *dp |= 1<<(x&07); | 
| 702 | + | err /= 3; | 
| 703 | + | cerr[x] = err + errp; | 
| 704 | + | } | 
| 705 | + | ynext++; | 
| 706 | + | } | 
| 707 | + |  | 
| 708 | + |  | 
| 709 |  | getfull()                       /* get full (24-bit) data */ | 
| 710 |  | { | 
| 711 |  | int     y; | 
| 721 |  | if (scale) | 
| 722 |  | shiftcolrs(scanline, xmax, scale); | 
| 723 |  | colrs_gambs(scanline, xmax); | 
| 724 | + | add2icon(y, scanline); | 
| 725 |  | for (x = 0; x < xmax; x++) { | 
| 726 |  | *dp++ = scanline[x][RED]; | 
| 727 |  | *dp++ = scanline[x][GRN]; | 
| 789 |  | quiterr("cannot seek for picreadline"); | 
| 790 |  | /* convert scanline */ | 
| 791 |  | normcolrs(scanline, xmax, scale); | 
| 792 | + | add2icon(y, scanline); | 
| 793 |  | for (i = 0; i < xmax; i++) { | 
| 794 |  | l3[i].r = scanline[i][RED]; | 
| 795 |  | l3[i].g = scanline[i][GRN]; |