home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / radsrc22 / src / px / ximage.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-21  |  15.5 KB  |  707 lines

  1. /* Copyright (c) 1987 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)ximage.c 2.6 8/21/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  ximage.c - driver for X-windows
  9.  *
  10.  *     4/30/87
  11.  *     3/3/88        Added calls to xraster & Paul Heckbert's ciq routines
  12.  */
  13.  
  14. #include  "standard.h"
  15.  
  16. #include  <X/Xlib.h>
  17. #include  <X/cursors/bcross.cursor>
  18. #include  <X/cursors/bcross_mask.cursor>
  19.  
  20. #include  <sys/types.h>
  21.  
  22. #include  <ctype.h>
  23.  
  24. #include  "color.h"
  25.  
  26. #include  "resolu.h"
  27.  
  28. #include  "xraster.h"
  29.  
  30. #include  "view.h"
  31.  
  32. #include  "pic.h"
  33.  
  34. #include  "random.h"
  35.  
  36. #define  controlshift(e)    (((XButtonEvent *)(e))->detail & (ShiftMask|ControlMask))
  37.  
  38. #define  FONTNAME    "9x15"        /* text font we'll use */
  39.  
  40. #define  CTRL(c)    ((c)-'@')
  41.  
  42. #define  BORWIDTH    5        /* border width */
  43. #define  BARHEIGHT    25        /* menu bar size */
  44.  
  45. double  gamcor = 2.2;            /* gamma correction */
  46.  
  47. XRASTER  *ourras = NULL;        /* our stored raster image */
  48.  
  49. int  dither = 1;            /* dither colors? */
  50. int  fast = 0;                /* keep picture in Pixmap? */
  51.  
  52. Window  wind = 0;            /* our output window */
  53. Font  fontid;                /* our font */
  54.  
  55. int  maxcolors = 0;            /* maximum colors */
  56. int  greyscale = 0;            /* in grey */
  57.  
  58. int  scale = 0;                /* scalefactor; power of two */
  59.  
  60. int  xoff = 0;                /* x image offset */
  61. int  yoff = 0;                /* y image offset */
  62.  
  63. VIEW  ourview = STDVIEW;        /* image view parameters */
  64. int  gotview = 0;            /* got parameters from file */
  65.  
  66. COLR  *scanline;            /* scan line buffer */
  67.  
  68. int  xmax, ymax;            /* picture resolution */
  69. int  width, height;            /* window size */
  70. char  *fname = NULL;            /* input file name */
  71. FILE  *fin = stdin;            /* input file */
  72. long  *scanpos = NULL;            /* scan line positions in file */
  73. int  cury = 0;                /* current scan location */
  74.  
  75. double  exposure = 1.0;            /* exposure compensation used */
  76.  
  77. int  wrongformat = 0;            /* input in another format */
  78.  
  79. struct {
  80.     int  xmin, ymin, xsiz, ysiz;
  81. }  box = {0, 0, 0, 0};            /* current box */
  82.  
  83. char  *geometry = NULL;            /* geometry specification */
  84.  
  85. char  *progname;
  86.  
  87. char  errmsg[128];
  88.  
  89. extern long  ftell();
  90.  
  91. extern char  *malloc(), *calloc();
  92.  
  93. extern double  pow(), log();
  94.  
  95.  
  96. main(argc, argv)
  97. int  argc;
  98. char  *argv[];
  99. {
  100.     extern char  *getenv();
  101.     char  *gv;
  102.     int  headline();
  103.     int  i;
  104.     
  105.     progname = argv[0];
  106.     if ((gv = getenv("GAMMA")) != NULL)
  107.         gamcor = atof(gv);
  108.  
  109.     for (i = 1; i < argc; i++)
  110.         if (argv[i][0] == '-')
  111.             switch (argv[i][1]) {
  112.             case 'c':
  113.                 maxcolors = atoi(argv[++i]);
  114.                 break;
  115.             case 'b':
  116.                 greyscale = !greyscale;
  117.                 break;
  118.             case 'm':
  119.                 maxcolors = 2;
  120.                 break;
  121.             case 'd':
  122.                 dither = !dither;
  123.                 break;
  124.             case 'f':
  125.                 fast = !fast;
  126.                 break;
  127.             case 'e':
  128.                 if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
  129.                     goto userr;
  130.                 scale = atoi(argv[++i]);
  131.                 break;
  132.             case 'g':
  133.                 gamcor = atof(argv[++i]);
  134.                 break;
  135.             default:
  136.                 goto userr;
  137.             }
  138.         else if (argv[i][0] == '=')
  139.             geometry = argv[i];
  140.         else
  141.             break;
  142.  
  143.     if (argc-i == 1) {
  144.         fname = argv[i];
  145.         fin = fopen(fname, "r");
  146.         if (fin == NULL) {
  147.             sprintf(errmsg, "can't open file \"%s\"", fname);
  148.             quiterr(errmsg);
  149.         }
  150.     }
  151.                 /* get header */
  152.     getheader(fin, headline, NULL);
  153.                 /* get picture dimensions */
  154.     if (wrongformat || fgetresolu(&xmax, &ymax, fin) != (YMAJOR|YDECR))
  155.         quiterr("bad picture size");
  156.                 /* set view parameters */
  157.     if (gotview && setview(&ourview) != NULL)
  158.         gotview = 0;
  159.     if ((scanline = (COLR *)malloc(xmax*sizeof(COLR))) == NULL)
  160.         quiterr("out of memory");
  161.  
  162.     init();            /* get file and open window */
  163.  
  164.     for ( ; ; )
  165.         getevent();        /* main loop */
  166. userr:
  167.     fprintf(stderr,
  168.     "Usage: %s [=geometry][-b][-m][-d][-f][-c ncolors][-e +/-stops] file\n",
  169.             progname);
  170.     quit(1);
  171. }
  172.  
  173.  
  174. headline(s)        /* get relevant info from header */
  175. char  *s;
  176. {
  177.     char  fmt[32];
  178.  
  179.     if (isexpos(s))
  180.         exposure *= exposval(s);
  181.     else if (isformat(s)) {
  182.         formatval(fmt, s);
  183.         wrongformat = strcmp(fmt, COLRFMT);
  184.     } else if (isview(s) && sscanview(&ourview, s) > 0)
  185.         gotview++;
  186. }
  187.  
  188.  
  189. init()            /* get data and open window */
  190. {
  191.     register int  i;
  192.     OpaqueFrame  mainframe;
  193.     char  defgeom[32];
  194.     
  195.     if (fname != NULL) {
  196.         scanpos = (long *)malloc(ymax*sizeof(long));
  197.         if (scanpos == NULL)
  198.             goto memerr;
  199.         for (i = 0; i < ymax; i++)
  200.             scanpos[i] = -1;
  201.     }
  202.     if (XOpenDisplay(NULL) == NULL)
  203.         quiterr("can't open display; DISPLAY variable set?");
  204. #ifdef notdef
  205.     if (DisplayWidth() - 2*BORWIDTH < xmax ||
  206.             DisplayHeight() - 2*BORWIDTH - BARHEIGHT < ymax)
  207.         quiterr("resolution mismatch");
  208. #endif
  209.     if (maxcolors == 0) {        /* get number of available colors */
  210.         maxcolors = 1<<DisplayPlanes();
  211.         if (maxcolors > 4) maxcolors -= 2;
  212.     }
  213.                 /* store image */
  214.     getras();
  215.  
  216.     mainframe.bdrwidth = BORWIDTH;
  217.     mainframe.border = WhitePixmap;
  218.     mainframe.background = BlackPixmap;
  219.     sprintf(defgeom, "=%dx%d+0+22", xmax, ymax);
  220.     wind = XCreate("Radiance Image", progname, geometry, defgeom,
  221.             &mainframe, 16, 16);
  222.     if (wind == 0)
  223.         quiterr("can't create window");
  224.     width = mainframe.width;
  225.     height = mainframe.height;
  226.     fontid = XGetFont(FONTNAME);
  227.     if (fontid == 0)
  228.         quiterr("can't get font");
  229.     XStoreName(wind, fname == NULL ? progname : fname);
  230.     XDefineCursor(wind, XCreateCursor(bcross_width, bcross_height,
  231.             bcross_bits, bcross_mask_bits,
  232.             bcross_x_hot, bcross_y_hot,
  233.             BlackPixel, WhitePixel, GXcopy));
  234.     XSelectInput(wind, ButtonPressed|ButtonReleased|UnmapWindow
  235.             |RightDownMotion|MiddleDownMotion|LeftDownMotion
  236.             |KeyPressed|ExposeWindow|ExposeRegion);
  237.     XMapWindow(wind);
  238.     return;
  239. memerr:
  240.     quiterr("out of memory");
  241. }
  242.  
  243.  
  244. quiterr(err)        /* print message and exit */
  245. char  *err;
  246. {
  247.     if (err != NULL)
  248.         fprintf(stderr, "%s: %s\n", progname, err);
  249.  
  250.     exit(err == NULL ? 0 : 1);
  251. }
  252.  
  253.  
  254. eputs(s)
  255. char    *s;
  256. {
  257.     fputs(s, stderr);
  258. }
  259.  
  260.  
  261. quit(code)
  262. int  code;
  263. {
  264.     exit(code);
  265. }
  266.  
  267.  
  268. getras()                /* get raster file */
  269. {
  270.     colormap    ourmap;
  271.  
  272.     ourras = (XRASTER *)calloc(1, sizeof(XRASTER));
  273.     if (ourras == NULL)
  274.         goto memerr;
  275.     ourras->width = xmax;
  276.     ourras->height = ymax;
  277.     if (maxcolors <= 2) {        /* monochrome */
  278.         ourras->data.m = (unsigned short *)malloc(BitmapSize(xmax,ymax));
  279.         if (ourras->data.m == NULL)
  280.             goto memerr;
  281.         getmono();
  282.     } else {
  283.         ourras->data.bz = (unsigned char *)malloc(BZPixmapSize(xmax,ymax));
  284.         if (ourras->data.bz == NULL)
  285.             goto memerr;
  286.         if (greyscale)
  287.             biq(dither,maxcolors,1,ourmap);
  288.         else
  289.             ciq(dither,maxcolors,1,ourmap);
  290.         if (init_rcolors(ourras, ourmap) == 0)
  291.             goto memerr;
  292.     }
  293.     return;
  294. memerr:
  295.     quiterr("out of memory");
  296. }
  297.  
  298.  
  299. getevent()                /* process the next event */
  300. {
  301.     WindowInfo  info;
  302.     XEvent  e;
  303.  
  304.     XNextEvent(&e);
  305.     switch (e.type) {
  306.     case KeyPressed:
  307.         docom(&e);
  308.         break;
  309.     case ExposeWindow:
  310.         XQueryWindow(wind, &info);    /* in case resized */
  311.         width = info.width;
  312.         height = info.height;
  313.     /* fall through */
  314.     case ExposeRegion:
  315.         fixwindow(&e);
  316.         break;
  317.     case UnmapWindow:
  318.         unmap_rcolors(ourras);
  319.         break;
  320.     case ButtonPressed:
  321.         if (controlshift(&e))
  322.             moveimage(&e);
  323.         else
  324.             getbox(&e);
  325.         break;
  326.     }
  327. }
  328.  
  329.  
  330. fixwindow(eexp)                /* fix new or stepped-on window */
  331. XExposeEvent  *eexp;
  332. {
  333.     redraw(eexp->x, eexp->y, eexp->width, eexp->height);
  334. }
  335.  
  336.  
  337. redraw(x, y, w, h)            /* redraw section of window */
  338. int  x, y;
  339. int  w, h;
  340. {
  341.     if (ourras->ncolors && map_rcolors(ourras) == NULL) {
  342.         fprintf(stderr, "%s: cannot allocate colors\n", progname);
  343.         return(-1);
  344.     }
  345.     if (fast)
  346.         make_rpixmap(ourras);
  347.     return(patch_raster(wind,x-xoff,y-yoff,x,y,w,h,ourras) ? 0 : -1);
  348. }
  349.  
  350.  
  351. docom(ekey)                    /* execute command */
  352. XKeyEvent  *ekey;
  353. {
  354.     char  buf[80];
  355.     COLOR  cval;
  356.     Color  cvx;
  357.     char  *cp;
  358.     int  n;
  359.     double  comp;
  360.     FVECT  rorg, rdir;
  361.  
  362.     cp = XLookupMapping(ekey, &n);
  363.     if (n == 0)
  364.         return(0);
  365.     switch (*cp) {            /* interpret command */
  366.     case 'q':
  367.     case CTRL('D'):                /* quit */
  368.         quit(0);
  369.     case '\n':
  370.     case '\r':
  371.     case 'l':
  372.     case 'c':                /* value */
  373.         if (avgbox(cval) == -1)
  374.             return(-1);
  375.         switch (*cp) {
  376.         case '\n':
  377.         case '\r':                /* radiance */
  378.             sprintf(buf, "%.3f", intens(cval)/exposure);
  379.             break;
  380.         case 'l':                /* luminance */
  381.             sprintf(buf, "%.0fL", luminance(cval)/exposure);
  382.             break;
  383.         case 'c':                /* color */
  384.             comp = pow(2.0, (double)scale);
  385.             sprintf(buf, "(%.2f,%.2f,%.2f)",
  386.                     colval(cval,RED)*comp,
  387.                     colval(cval,GRN)*comp,
  388.                     colval(cval,BLU)*comp);
  389.             break;
  390.         }
  391.         XText(wind, box.xmin, box.ymin, buf, strlen(buf),
  392.                 fontid, BlackPixel, WhitePixel);
  393.         return(0);
  394.     case 'i':                /* identify (contour) */
  395.         if (ourras->pixels == NULL)
  396.             return(-1);
  397.         n = ourras->data.bz[ekey->x-xoff+BZPixmapSize(xmax,ekey->y-yoff)];
  398.         n = ourras->pmap[n];
  399.         cvx.pixel = ourras->cdefs[n].pixel;
  400.         cvx.red = random() & 65535;
  401.         cvx.green = random() & 65535;
  402.         cvx.blue = random() & 65535;
  403.         XStoreColor(&cvx);
  404.         return(0);
  405.     case 'p':                /* position */
  406.         sprintf(buf, "(%d,%d)", ekey->x-xoff, ymax-1-ekey->y+yoff);
  407.         XText(wind, ekey->x, ekey->y, buf, strlen(buf),
  408.                 fontid, BlackPixel, WhitePixel);
  409.         return(0);
  410.     case 't':                /* trace */
  411.         if (!gotview) {
  412.             XFeep(0);
  413.             return(-1);
  414.         }
  415.         if (viewray(rorg, rdir, &ourview, (ekey->x-xoff+.5)/xmax,
  416.                 (ymax-1-ekey->y+yoff+.5)/ymax) < 0)
  417.             return(-1);
  418.         printf("%e %e %e ", rorg[0], rorg[1], rorg[2]);
  419.         printf("%e %e %e\n", rdir[0], rdir[1], rdir[2]);
  420.         fflush(stdout);
  421.         return(0);
  422.     case '=':                /* adjust exposure */
  423.         if (avgbox(cval) == -1)
  424.             return(-1);
  425.         n = log(.5/bright(cval))/.69315 - scale;    /* truncate */
  426.         if (n == 0)
  427.             return(0);
  428.         scale_rcolors(ourras, pow(2.0, (double)n));
  429.         scale += n;
  430.         sprintf(buf, "%+d", scale);
  431.         XText(wind, box.xmin, box.ymin, buf, strlen(buf),
  432.                 fontid, BlackPixel, WhitePixel);
  433.         XFlush();
  434.         free_raster(ourras);
  435.         getras();
  436.     /* fall through */
  437.     case CTRL('R'):                /* redraw */
  438.     case CTRL('L'):
  439.         unmap_rcolors(ourras);
  440.         XClear(wind);
  441.         return(redraw(0, 0, width, height));
  442.     case ' ':                /* clear */
  443.         return(redraw(box.xmin, box.ymin, box.xsiz, box.ysiz));
  444.     default:
  445.         XFeep(0);
  446.         return(-1);
  447.     }
  448. }
  449.  
  450.  
  451. moveimage(ep)                /* shift the image */
  452. XButtonEvent  *ep;
  453. {
  454.     XButtonEvent  eb;
  455.  
  456.     XMaskEvent(ButtonReleased, &eb);
  457.     xoff += eb.x - ep->x;
  458.     yoff += eb.y - ep->y;
  459.     XClear(wind);
  460.     return(redraw(0, 0, width, height));
  461. }
  462.  
  463.  
  464. getbox(ebut)                /* get new box */
  465. XButtonEvent  *ebut;
  466. {
  467.     union {
  468.         XEvent  e;
  469.         XButtonEvent  b;
  470.         XMouseMovedEvent  m;
  471.     }  e;
  472.  
  473.     XMaskEvent(ButtonReleased|MouseMoved, &e.e);
  474.     while (e.e.type == MouseMoved) {
  475.         revbox(ebut->x, ebut->y, box.xmin = e.m.x, box.ymin = e.m.y);
  476.         XMaskEvent(ButtonReleased|MouseMoved, &e.e);
  477.         revbox(ebut->x, ebut->y, box.xmin, box.ymin);
  478.     }
  479.     box.xmin = e.b.x<0 ? 0 : (e.b.x>=width ? width-1 : e.b.x);
  480.     box.ymin = e.b.y<0 ? 0 : (e.b.y>=height ? height-1 : e.b.y);
  481.     if (box.xmin > ebut->x) {
  482.         box.xsiz = box.xmin - ebut->x + 1;
  483.         box.xmin = ebut->x;
  484.     } else {
  485.         box.xsiz = ebut->x - box.xmin + 1;
  486.     }
  487.     if (box.ymin > ebut->y) {
  488.         box.ysiz = box.ymin - ebut->y + 1;
  489.         box.ymin = ebut->y;
  490.     } else {
  491.         box.ysiz = ebut->y - box.ymin + 1;
  492.     }
  493. }
  494.  
  495.  
  496. revbox(x0, y0, x1, y1)            /* draw box with reversed lines */
  497. int  x0, y0, x1, y1;
  498. {
  499.     XLine(wind, x0, y0, x1, y0, 1, 1, 0, GXinvert, AllPlanes);
  500.     XLine(wind, x0, y1, x1, y1, 1, 1, 0, GXinvert, AllPlanes);
  501.     XLine(wind, x0, y0, x0, y1, 1, 1, 0, GXinvert, AllPlanes);
  502.     XLine(wind, x1, y0, x1, y1, 1, 1, 0, GXinvert, AllPlanes);
  503. }
  504.  
  505.  
  506. avgbox(clr)                /* average color over current box */
  507. COLOR  clr;
  508. {
  509.     int  left, right, top, bottom;
  510.     int  y;
  511.     double  d;
  512.     COLOR  ctmp;
  513.     register int  x;
  514.  
  515.     setcolor(clr, 0.0, 0.0, 0.0);
  516.     left = box.xmin - xoff;
  517.     right = left + box.xsiz;
  518.     if (left < 0)
  519.         left = 0;
  520.     if (right > xmax)
  521.         right = xmax;
  522.     if (left >= right)
  523.         return(-1);
  524.     top = box.ymin - yoff;
  525.     bottom = top + box.ysiz;
  526.     if (top < 0)
  527.         top = 0;
  528.     if (bottom > ymax)
  529.         bottom = ymax;
  530.     if (top >= bottom)
  531.         return(-1);
  532.     for (y = top; y < bottom; y++) {
  533.         if (getscan(y) == -1)
  534.             return(-1);
  535.         for (x = left; x < right; x++) {
  536.             colr_color(ctmp, scanline[x]);
  537.             addcolor(clr, ctmp);
  538.         }
  539.     }
  540.     d = 1.0/((right-left)*(bottom-top));
  541.     scalecolor(clr, d);
  542.     return(0);
  543. }
  544.  
  545.  
  546. getmono()            /* get monochrome data */
  547. {
  548.     register unsigned short    *dp;
  549.     register int    x, err;
  550.     int    y, errp;
  551.     rgbpixel    *inl;
  552.     short    *cerr;
  553.  
  554.     if ((inl = (rgbpixel *)malloc(xmax*sizeof(rgbpixel))) == NULL
  555.             || (cerr = (short *)calloc(xmax,sizeof(short))) == NULL)
  556.         quiterr("out of memory in getmono");
  557.     dp = ourras->data.m - 1;
  558.     for (y = 0; y < ymax; y++) {
  559.         picreadline3(y, inl);
  560.         err = 0;
  561.         for (x = 0; x < xmax; x++) {
  562.             if (!(x&0xf))
  563.                 *++dp = 0;
  564.             errp = err;
  565.             err += rgb_bright(&inl[x]) + cerr[x];
  566.             if (err > 127)
  567.                 err -= 255;
  568.             else
  569.                 *dp |= 1<<(x&0xf);
  570.             err /= 3;
  571.             cerr[x] = err + errp;
  572.         }
  573.     }
  574.     free((char *)inl);
  575.     free((char *)cerr);
  576. }
  577.  
  578.  
  579. init_rcolors(xr, cmap)                /* (re)assign color values */
  580. register XRASTER    *xr;
  581. colormap    cmap;
  582. {
  583.     register int    i;
  584.     register unsigned char    *p;
  585.  
  586.     xr->pmap = (int *)malloc(256*sizeof(int));
  587.     if (xr->pmap == NULL)
  588.         return(0);
  589.     xr->cdefs = (Color *)malloc(256*sizeof(Color));
  590.     if (xr->cdefs == NULL)
  591.         return(0);
  592.     for (i = 0; i < 256; i++)
  593.         xr->pmap[i] = -1;
  594.     xr->ncolors = 0;
  595.     for (p = xr->data.bz, i = BZPixmapSize(xr->width,xr->height); i--; p++)
  596.         if (xr->pmap[*p] == -1) {
  597.             xr->cdefs[xr->ncolors].red = cmap[0][*p] << 8;
  598.             xr->cdefs[xr->ncolors].green = cmap[1][*p] << 8;
  599.             xr->cdefs[xr->ncolors].blue = cmap[2][*p] << 8;
  600.             xr->cdefs[xr->ncolors].pixel = *p;
  601.             xr->pmap[*p] = xr->ncolors++;
  602.         }
  603.     xr->cdefs = (Color *)realloc((char *)xr->cdefs, xr->ncolors*sizeof(Color));
  604.     if (xr->cdefs == NULL)
  605.         return(0);
  606.     return(1);
  607. }
  608.  
  609.  
  610. scale_rcolors(xr, sf)            /* scale color map */
  611. register XRASTER    *xr;
  612. double    sf;
  613. {
  614.     register int    i;
  615.     long    maxv;
  616.  
  617.     if (xr->pixels == NULL)
  618.         return;
  619.  
  620.     sf = pow(sf, 1.0/gamcor);
  621.     maxv = 65535/sf;
  622.  
  623.     for (i = xr->ncolors; i--; ) {
  624.         xr->cdefs[i].red = xr->cdefs[i].red > maxv ?
  625.                 65535 :
  626.                 xr->cdefs[i].red * sf;
  627.         xr->cdefs[i].green = xr->cdefs[i].green > maxv ?
  628.                 65535 :
  629.                 xr->cdefs[i].green * sf;
  630.         xr->cdefs[i].blue = xr->cdefs[i].blue > maxv ?
  631.                 65535 :
  632.                 xr->cdefs[i].blue * sf;
  633.     }
  634.     XStoreColors(xr->ncolors, xr->cdefs);
  635. }
  636.  
  637.  
  638. getscan(y)
  639. int  y;
  640. {
  641.     if (y != cury) {
  642.         if (scanpos == NULL || scanpos[y] == -1)
  643.             return(-1);
  644.         if (fseek(fin, scanpos[y], 0) == -1)
  645.             quiterr("fseek error");
  646.         cury = y;
  647.     } else if (scanpos != NULL && scanpos[y] == -1)
  648.         scanpos[y] = ftell(fin);
  649.  
  650.     if (freadcolrs(scanline, xmax, fin) < 0)
  651.         quiterr("read error");
  652.  
  653.     cury++;
  654.     return(0);
  655. }
  656.  
  657.  
  658. picreadline3(y, l3)            /* read in 3-byte scanline */
  659. int  y;
  660. register rgbpixel  *l3;
  661. {
  662.     register int    i;
  663.                             /* read scanline */
  664.     if (getscan(y) < 0)
  665.         quiterr("cannot seek for picreadline");
  666.                             /* convert scanline */
  667.     normcolrs(scanline, xmax, scale);
  668.     for (i = 0; i < xmax; i++) {
  669.         l3[i].r = scanline[i][RED];
  670.         l3[i].g = scanline[i][GRN];
  671.         l3[i].b = scanline[i][BLU];
  672.     }
  673. }
  674.  
  675.  
  676. picwriteline(y, l)        /* add 8-bit scanline to image */
  677. int  y;
  678. pixel  *l;
  679. {
  680.     bcopy((char *)l, (char *)ourras->data.bz+BZPixmapSize(xmax,y), BZPixmapSize(xmax,1));
  681. }
  682.  
  683.  
  684. picreadcm(map)            /* do gamma correction */
  685. colormap  map;
  686. {
  687.     extern double  pow();
  688.     register int  i, val;
  689.  
  690.     for (i = 0; i < 256; i++) {
  691.         val = pow((i+0.5)/256.0, 1.0/gamcor) * 256.0;
  692.         map[0][i] = map[1][i] = map[2][i] = val;
  693.     }
  694. }
  695.  
  696.  
  697. picwritecm(map)            /* handled elsewhere */
  698. colormap  map;
  699. {
  700. #ifdef DEBUG
  701.     register int i;
  702.  
  703.     for (i = 0; i < 256; i++)
  704.         printf("%d %d %d\n", map[0][i],map[1][i],map[2][i]);
  705. #endif
  706. }
  707.