[comp.graphics] X11R3/R4 Xlib Greyscale Image Display Routine

dra@neuro.usc.edu (Diane Annala) (09/30/90)

The following code fragment depends only on the X11R3/R4 Xlib -- Please note
that it is somewhat unusual in that it draws directly from an ximage struct
(in the client process) to the mapped window (in the server process).  This
was necessary in order to avoid allocating a large pixmap (in the server) to
contain an off screen copy of large (e.g. 4K x 4K) images.  Allocating such
a large pixmap causes the server memory demands to increase dramatically --
such increased memory demands caused excessive paging on my 8mb SUN3/160C.

    sun os compile:  cc foo4.c -o foo4 -lX11
    unicos compile:  cc foo4.c -o foo4 -lX11 -lnet

    foo4 -in greyscale.img -w 512 -h 512

      -in specifies raw pixel file to read in
      -w  specified number of pixels in horizontal dimension
      -h  specified number of pixels in vertical dimension

--d 
================================== CUT HERE ================================
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <string.h>

#define max(a,b)    (( (a) > (b) ) ? (a) : (b) )
#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 = 640, height = 480;
unsigned int imwidth = 512, imheight = 512;
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;
int ncolors=256;
int isize=16;
FILE *f;
unsigned char *data;
int a;
Pixmap pic;
XImage *image;
char *infilename = "feath.bw"; 
XSetWindowAttributes setwinattr;

main(argc, argv)
  int argc;
  char *argv[];
{
  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);

  XChangeProperty(display, window, XA_WM_NAME, XA_STRING, 8, PropModeReplace, 
                  " X11 Image Processing System  --  ", 
           strlen(" X11 Image Processing System  --  "));

  XChangeProperty(display, window, XA_WM_NAME, XA_STRING, 8, PropModeAppend, 
                  " Annala Research Inc. 1990", 
           strlen(" Annala Research Inc. 1990"));

  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 ;
    }

  colors[1].red   =   0<<8;
  colors[1].green = 224<<8;
  colors[1].blue  =   0<<8;

  colors[2].red   =   0<<8;
  colors[2].green =  64<<8;
  colors[2].blue  =   0<<8;

  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 ((data=(unsigned char *)malloc(imheight*imwidth))==NULL)
    {
      fprintf(stderr,"malloc error\n");
      exit(1);
    }
  for (a=0; a<imheight; a++)
    {
      if (fread(data+(a*imwidth), imwidth, 1, f) != 1)
        {
          fprintf(stderr,"read error -- maybe short image\n");
          exit(1);
        }
    }  
  image=XCreateImage(display,visual,8,ZPixmap,0,data,imwidth,imheight,8,imwidth);
  image->byte_order=MSBFirst;
  image->bitmap_bit_order=MSBFirst;
  values.function=GXcopy;
  gc = XCreateGC(display, window, GCFunction, &values);
  /************************************************************************/

  while (1)
    {
      XNextEvent(display, &report);
      switch(report.type)
        {
          case Expose:
              XPutImage(display, window, gc, image,
                        report.xexpose.x+imx, report.xexpose.y+imy,
                        max(report.xexpose.x,-imx), max(report.xexpose.y,-imy), 
                        report.xexpose.width,
                        report.xexpose.height );
            break;
          case ButtonPress:
            {
            switch(report.xbutton.button)
              {
                case Button1:
                  imx = imx+report.xbutton.x-(width>>1);
                  imy = imy+report.xbutton.y-(height>>1);
                  if ( (imx<0) || (imy<0) ||
                       (max(0, width-max(0,-imx))>max(0, imwidth-max(0,imx))) ||
                       (max(0,height-max(0,-imy))>max(0,imheight-max(0,imy))) )
                    XClearWindow(display, window);
                  XPutImage(display, window, gc, image, 
                            max(0,imx), max(0,imy), 
                            max(0,-imx), max(0,-imy), 
                            (max(0,min(max(0,   width-max(0,-imx)), 
                                       max(0, imwidth-max(0, imx)) ) )) , 
                            (max(0,min(max(0,  height-max(0,-imy)), 
                                       max(0,imheight-max(0, imy)) ) )) );
                  break;
                case Button2:
                  XPutImage(display, window, gc, image, 0, 0, 0, 0, width, height);
                  break;
                case Button3:
                  XUnloadFont(display, font_info->fid);
                  XFreeGC(display,gc);
                  XCloseDisplay(display);
                  exit(1);
                  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;
	}
    }
}