From: merlin@neuro.usc.edu (merlin)
Newsgroups: sci.med.physics
Subject: SUN X11 Viewer for Chapel Hill 3D MRI of Human Head
Date: 17 Aug 1992 02:20:55 -0700
Organization: University of Southern California, Los Angeles, CA
NNTP-Posting-Host: neuro.usc.edu

/***

purpose:  SUN X11 viewer for omicron.cs.unc.edu:/pub/softlab/CHVRTD/volI/3dhead

status:   quick & dirty first attempt at interactive X11 based image viewing tool

data:     the 14 MByte 3D MRI of the human head may be obtained by anonymous ftp:

          ftp -i omicron.cs.unc.edu
          username:  anonymous
          password:  yourname@yoursite.yourcampus.edu
          ftp> cd pub/softlab/CHVRTD
          ftp> binary
          ftp> get 3dhead
          ftp> quit

compile:  cc -o vhead vhead.c -L/usr/public/X11/lib -lX11

run:      setenv DISPLAY yourhost:0.0; foo9

          this program simultaneously displays parasagital, coronal, and horizontal
          MRI slices from a human head -- within any one of these three images the
          left and right mouse buttons cause the display to increment one image at
          a time while the middle mouse button will rapidly advance to the position
          marked by the position of the cursor along a vertical line in each slice. 

author:   alexander-james annala

          principal investigator
          neuroscience image analysis network

          -- and --

          ph.d. graduate student            
          neuroscience program

          hedco neuroscience bldg, room 534a
          university of southern california
          los angeles, ca 90089-2520

***/

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <stdio.h>

#define min(a,b) (((a) < (b)) ? (a) : (b))

char *display_name = NULL;
Display *display;
int screen;
Colormap colormap;
XColor colors[256], fg_color, bg_color;
Window window;
unsigned int width = 1166, height = 512;
unsigned int imwidth = 256, imheight = 256;
int imx = 0, imy = 0;
int x = 0, y = 0;
unsigned int border_width = 4;
XEvent report;
GC gc;
XFontStruct *font_info;
char *fontname = "9x15";
unsigned long valuemask = 0;
XGCValues values;
Visual *visual=NULL;
int i, j, k, k1, k2, k3;
int ncolors=256;
int isize=16;
FILE *f;
unsigned char *data;
unsigned short *datas;
int a, tmp;
Pixmap pic;
XImage *image;
char *infilename = "3dhead"; 
unsigned char *ptr;
XSetWindowAttributes setwinattr;

main(argc, argv)
  int argc;
  char *argv[];
{
  k1=54;
  k2=128;
  k3=128;
  for (a=1; (a<argc) && (*argv[a]=='-'); a++)
    if (!strcmp("-in", argv[a]))
      infilename=argv[++a];
    else if (!strcmp("-w", argv[a]))
      imwidth=atoi(argv[++a]);
    else if (!strcmp("-h", argv[a]))
      imheight=atoi(argv[++a]);

  if ((display=XOpenDisplay(display_name))==NULL)
    {
      fprintf(stderr, "cannot connect to server %s\n",
        XDisplayName(display_name));
      exit(-1);
    }
  screen = DefaultScreen(display);
  visual = XDefaultVisual(display, screen);
  window = XCreateSimpleWindow(display, RootWindow(display,screen),
             x, y, width, height, border_width,
             BlackPixel(display,screen),
             WhitePixel(display,screen));
  valuemask = CWBackingStore;
  setwinattr.backing_store = NotUseful;
  XChangeWindowAttributes(display, window, valuemask, &setwinattr);

  XMapWindow(display, window);

  XSelectInput(display, window, ExposureMask|KeyPressMask|ButtonPressMask|
                                StructureNotifyMask);

  if ((font_info=XLoadQueryFont(display, fontname))==NULL)
    {
      fprintf(stderr,"cannot load font %s\n", fontname);
      exit(-1);
    }

  for (i=0; i<ncolors; i++)
    {
      colors[i].pixel = (u_long)(i);
      colors[i].red   = (u_short)(i<<8);
      colors[i].green = (u_short)(i<<8);
      colors[i].blue  = (u_short)(i<<8);
      colors[i].flags = DoRed | DoGreen | DoBlue ;
    }

  colormap=XCreateColormap(display, window, visual, AllocAll);
  XStoreColors(display, colormap, colors, ncolors);
  XSetWindowColormap(display, window, colormap);

  gc = XCreateGC(display, window, 0, &values);
  XSetForeground(display, gc, WhitePixel(display, screen));
  XSetBackground(display, gc, BlackPixel(display, screen));

  /************************************************************************/
  f = fopen(infilename,"r");

  if ((datas=(unsigned short *)malloc(imheight*imwidth*109*2))==NULL)
    {
      fprintf(stderr,"malloc error 1\n");
      exit(1);
    }
  if (fread(datas, imwidth*imheight*109*2, 1, f) != 1)
    {
      fprintf(stderr,"read error -- maybe short image\n");
      exit(1);
    }
  if ((data=(unsigned char *)malloc(imheight*imwidth*4))==NULL)
    {
      fprintf(stderr,"malloc error 2\n");
      exit(1);
    }
  for (i=0; i<(imheight*imwidth*109); i++)
    {
      ptr = (unsigned char *) (datas+i);
      tmp = *(ptr);
      *ptr = *(ptr+1);
      *(ptr+1) = tmp;
      *(datas+i) = (*(datas+i)) >> 3;
      
    }

  pic = XCreatePixmap(display, window, (imwidth*2), (imheight*2), 8);
  image=XCreateImage(display,visual,8,ZPixmap,0,data,(imwidth*2),(imheight*2),8,(imwidth*2));
  image->byte_order=MSBFirst;
  image->bitmap_bit_order=MSBFirst;
  values.function=GXcopy;
  gc = XCreateGC(display, pic, GCFunction, &values);
  XPutImage(display, pic, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));
  /************************************************************************/
  k=0;
  while (1)
    {
      XNextEvent(display, &report);
      switch(report.type)
        {
          case Expose:
		  {
                  for (j=0; j<(imheight); j++)
                    for (i=0; i<(imwidth); i++)
                      { 
                        tmp = min(255, *(datas+(k1<<16)+(j*imwidth)+i));
		        *(data+(((j*4)*imwidth)+(i*2))) = tmp;
		        *(data+(((j*4)*imwidth)+(i*2)+1)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*2))) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*2)+1)) = tmp;
                      }
		  XPutImage(display, window, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));
                  /*** XPutImage(display, pic, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));  ***/
                  /*** XCopyArea(display, pic, window, gc, 0, 0, (imwidth*2), (imheight*2), 0, 0); ***/

                  for (j=0; j<(imheight); j++)
                    for (i=0; i<(109); i++)
                      {
                        tmp = min(255, *(datas+(i<<16)+(j*imwidth)+k2));
		        *(data+(((j*4)*imwidth)+(i*3))) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+1)) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+2)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3))) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+1)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+2)) = tmp;
                      }
		  XPutImage(display, window, gc, image, 0, 0, 512, 0, (109*3), (imheight*2));
                  /*** XPutImage(display, pic, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));  ***/
                  /*** XCopyArea(display, pic, window, gc, 0, 0, (imwidth*2), (imheight*2), 0, 0); ***/

                  for (j=0; j<(imheight); j++)
                    for (i=0; i<(109); i++)
                      {
                        tmp = min(255, *(datas+(i<<16)+(k3*imwidth)+j));
		        *(data+(((j*4)*imwidth)+(i*3))) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+1)) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+2)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3))) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+1)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+2)) = tmp;
                      }
		  XPutImage(display, window, gc, image, 0, 0, 839, 0, (109*3), (imheight*2));
                  /*** XPutImage(display, pic, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));  ***/
                  /*** XCopyArea(display, pic, window, gc, 0, 0, (imwidth*2), (imheight*2), 0, 0); ***/

		  }
            break;
          case ButtonPress:
            {
            switch(report.xbutton.button)
              {
                case Button1:
		  {
                  if (report.xbutton.x < 512) 
		  {
                  if (k1 < 108)
                    k1 = k1 + 1;
                  for (j=0; j<(imheight); j++)
                    for (i=0; i<(imwidth); i++)
                      {
                        tmp = min(255, *(datas+(k1<<16)+(j*imwidth)+i));
		        *(data+(((j*4)*imwidth)+(i*2))) = tmp;
		        *(data+(((j*4)*imwidth)+(i*2)+1)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*2))) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*2)+1)) = tmp;
                      }
		  XPutImage(display, window, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));
                  /*** XPutImage(display, pic, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));  ***/
                  /*** XCopyArea(display, pic, window, gc, 0, 0, (imwidth*2), (imheight*2), 0, 0); ***/
		  }
                  if ( (report.xbutton.x > 512) && (report.xbutton.x < 839) )
		  {
                  if (k2 < 255)
                    k2 = k2 + 1;
                  for (j=0; j<(imheight); j++)
                    for (i=0; i<(109); i++)
                      {
                        tmp = min(255, *(datas+(i<<16)+(j*imwidth)+k2));
		        *(data+(((j*4)*imwidth)+(i*3))) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+1)) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+2)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3))) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+1)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+2)) = tmp;
                      }
		  XPutImage(display, window, gc, image, 0, 0, 512, 0, (109*3), (imheight*2));
                  /*** XPutImage(display, pic, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));  ***/
                  /*** XCopyArea(display, pic, window, gc, 0, 0, (imwidth*2), (imheight*2), 0, 0); ***/
		  }
                  if ( report.xbutton.x > 840 )
		  {
                  if (k3 < 255)
                    k3 = k3 + 1;
                  for (j=0; j<(imheight); j++)
                    for (i=0; i<(109); i++)
                      {
                        tmp = min(255, *(datas+(i<<16)+(k3*imwidth)+j));
		        *(data+(((j*4)*imwidth)+(i*3))) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+1)) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+2)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3))) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+1)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+2)) = tmp;
                      }
		  XPutImage(display, window, gc, image, 0, 0, 839, 0, (109*3), (imheight*2));
                  /*** XPutImage(display, pic, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));  ***/
                  /*** XCopyArea(display, pic, window, gc, 0, 0, (imwidth*2), (imheight*2), 0, 0); ***/
		  }
		  }
                  break;
                case Button2:
		  {
                  if (report.xbutton.x < 512) 
		  {
                  k1 = report.xbutton.y * 109 / height;
                  for (j=0; j<(imheight); j++)
                    for (i=0; i<(imwidth); i++)
                      {
                        tmp = min(255, *(datas+(k1<<16)+(j*imwidth)+i));
		        *(data+(((j*4)*imwidth)+(i*2))) = tmp;
		        *(data+(((j*4)*imwidth)+(i*2)+1)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*2))) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*2)+1)) = tmp;
                      }
		  XPutImage(display, window, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));
                  /*** XPutImage(display, pic, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));  ***/
                  /*** XCopyArea(display, pic, window, gc, 0, 0, (imwidth*2), (imheight*2), 0, 0); ***/
		  }
                  if ( (report.xbutton.x > 512) && (report.xbutton.x < 839) )
		  {
                  k2 = report.xbutton.y * 256 / height;
                  for (j=0; j<(imheight); j++)
                    for (i=0; i<(109); i++)
                      {
                        tmp = min(255, *(datas+(i<<16)+(j*imwidth)+k2));
		        *(data+(((j*4)*imwidth)+(i*3))) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+1)) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+2)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3))) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+1)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+2)) = tmp;
                      }
		  XPutImage(display, window, gc, image, 0, 0, 512, 0, (109*3), (imheight*2));
                  /*** XPutImage(display, pic, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));  ***/
                  /*** XCopyArea(display, pic, window, gc, 0, 0, (imwidth*2), (imheight*2), 0, 0); ***/
		  }
                  if ( report.xbutton.x > 840 )
		  {
                  k3 = report.xbutton.y * 256 / height;
                  for (j=0; j<(imheight); j++)
                    for (i=0; i<(109); i++)
                      {
                        tmp = min(255, *(datas+(i<<16)+(k3*imwidth)+j));
		        *(data+(((j*4)*imwidth)+(i*3))) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+1)) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+2)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3))) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+1)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+2)) = tmp;
                      }
		  XPutImage(display, window, gc, image, 0, 0, 839, 0, (109*3), (imheight*2));
                  /*** XPutImage(display, pic, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));  ***/
                  /*** XCopyArea(display, pic, window, gc, 0, 0, (imwidth*2), (imheight*2), 0, 0); ***/
		  }
		  }
                  break;
                case Button3:
		  {
                  if (report.xbutton.x < 512) 
		  {
                  if (k1 > 0)
                    k1 = k1 - 1;
                  for (j=0; j<(imheight); j++)
                    for (i=0; i<(imwidth); i++)
                      {
                        tmp = min(255, *(datas+(k1<<16)+(j*imwidth)+i));
		        *(data+(((j*4)*imwidth)+(i*2))) = tmp;
		        *(data+(((j*4)*imwidth)+(i*2)+1)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*2))) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*2)+1)) = tmp;
                      }
		  XPutImage(display, window, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));
                  /*** XPutImage(display, pic, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));  ***/
                  /*** XCopyArea(display, pic, window, gc, 0, 0, (imwidth*2), (imheight*2), 0, 0); ***/
		  }
                  if ( (report.xbutton.x > 512) && (report.xbutton.x < 839) )
		  {
                  if (k2 > 0)
                    k2 = k2 - 1;
                  for (j=0; j<(imheight); j++)
                    for (i=0; i<(109); i++)
                      {
                        tmp = min(255, *(datas+(i<<16)+(j*imwidth)+k2));
		        *(data+(((j*4)*imwidth)+(i*3))) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+1)) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+2)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3))) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+1)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+2)) = tmp;
                      }
		  XPutImage(display, window, gc, image, 0, 0, 512, 0, (109*3), (imheight*2));
                  /*** XPutImage(display, pic, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));  ***/
                  /*** XCopyArea(display, pic, window, gc, 0, 0, (imwidth*2), (imheight*2), 0, 0); ***/
		  }
                  if ( report.xbutton.x > 840 )
		  {
                  if (k3 > 0)
                    k3 = k3 - 1;
                  for (j=0; j<(imheight); j++)
                    for (i=0; i<(109); i++)
                      {
                        tmp = min(255, *(datas+(i<<16)+(k3*imwidth)+j));
		        *(data+(((j*4)*imwidth)+(i*3))) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+1)) = tmp;
		        *(data+(((j*4)*imwidth)+(i*3)+2)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3))) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+1)) = tmp;
		        *(data+((((j*4)+2)*imwidth)+(i*3)+2)) = tmp;
                      }
		  XPutImage(display, window, gc, image, 0, 0, 839, 0, (109*3), (imheight*2));
                  /*** XPutImage(display, pic, gc, image, 0, 0, 0, 0, (imwidth*2), (imheight*2));  ***/
                  /*** XCopyArea(display, pic, window, gc, 0, 0, (imwidth*2), (imheight*2), 0, 0); ***/
		  }
		  }
                  break;
		default:
                  break;
	      }
	    }
            break;
          case ConfigureNotify:
            width = report.xconfigure.width;
            height = report.xconfigure.height;
            break;
          case KeyPress:
            XUnloadFont(display, font_info->fid);
            XFreeGC(display,gc);
            XCloseDisplay(display);
            exit(1);
          default:
            break;
	}
    }
}