#include #include #include #include Display *dpy; /* X server we're talking to */ Window win; /* Window to paint the image in */ GC gc; /* GC to use for painting */ Visual *visual; /* Visual to use for the window */ Colormap cmap; /* Colormap to use for painting */ XEvent ev; /* Event received from the server */ XImage *image; /* To hold the image to be painted */ int width, height; /* Size of the window */ int best_size[6]; /* Largest colormap per Visual class */ XVisualInfo *best_vis[6]; /* Best Visual per Visual class */ int best_class[] = { TrueColor, DirectColor, PseudoColor, StaticColor, GrayScale, StaticGray }; /* * Return the most suitable Visual for representing numcolors colors */ XVisualInfo * FindVisual(numcolors) int numcolors; { int num_vis, i, big_map = 0; XVisualInfo vinfo_template, *vlist, *v, *big_vis = NULL; /* Get descriptions of all the visuals */ vlist = XGetVisualInfo(dpy, VisualNoMask, &vinfo_template, &num_vis); /* Scan the list examining the colormap size */ for (v = vlist; v < vlist + num_vis; v++) { /* Remember the biggest colormap among all classes */ if (v->colormap_size > big_map) { big_map = v->colormap_size; big_vis = v; } /* If the colormap is big enough, remember it */ if (v->colormap_size > numcolors) { if ((best_size[v->class] == 0) || (v->colormap_size < best_size[v->class])) { /* Smallest so far that'll do */ best_size[v->class] = v->colormap_size; best_vis[v->class] = v; } } } /* In decreasing order of usability, look at each class */ for (i = 0; i < 6; i++) if (best_size[best_class[i]] > numcolors) /* This class can represent enough colors */ return (best_vis[best_class[i]]); /* Sigh! We'll have to make do with a Visual that's too small */ return (big_vis); } main(argc, argv) int argc; char **argv; { int numcolors, num_pxls, num_vis, x, y; unsigned short *rgbvalues; XVisualInfo *vis; XSetWindowAttributes values; XColor color; /* Read the size information from stdin */ fread((char *) &width, sizeof(int), 1, stdin); fread((char *) &height, sizeof(int), 1, stdin); fread((char *) &numcolors, sizeof(int), 1, stdin); /* Allocate space to hold the RGB data, and read it in */ num_pxls = width * height; rgbvalues = (unsigned short *) malloc(sizeof(unsigned short) * 3 * num_pxls); fread((char *) rgbvalues, sizeof(unsigned short), 3 * num_pxls, stdin); /* Connect to the server */ if ((dpy = XOpenDisplay(NULL)) == (Display *) 0) { fprintf(stderr, "can't open display\n"); exit(1); } /* Find a suitable Visual for numcolors */ vis = FindVisual(numcolors); /* Create a Colormap in the Visual we found */ cmap = XCreateColormap(dpy, RootWindow(dpy, DefaultScreen(dpy)), vis->visual, AllocNone); /* Create an image the right size */ image = XCreateImage(dpy, vis->visual, vis->depth, ZPixmap, 0, (unsigned long *) malloc(num_pxls * sizeof(unsigned long)), width, height, 32, 0); /* For each pixel in the image */ for (y = 0; y < height; y++) for (x = 0; x < width; x++) { /* Fill out the RGB fields of the XColor struct */ color.red = *rgbvalues++; color.green = *rgbvalues++; color.blue = *rgbvalues++; color.flags = DoRed | DoGreen | DoBlue; /* Get the server to convert from RGB to pixel value */ if (!XAllocColor(dpy, cmap, &color)) { /* The colormap filled up - give up */ fprintf(stderr, "Colormap full\n"); exit(1); } /* Put the pixel value into the image */ (void) XPutPixel(image, x, y, color.pixel); } /* Create a suitable window using the Colormap, background White */ values.colormap = cmap; /* get White from our colormap */ XAllocNamedColor(dpy, cmap, "white", &color, &color); values.background_pixel = color.pixel; /* Listen for Expose, Enter and Leave events */ values.event_mask = ExposureMask | EnterWindowMask | LeaveWindowMask; win = XCreateWindow(dpy, RootWindow(dpy, DefaultScreen(dpy)), 0, 0, width, height, 0, vis->depth, InputOutput, vis->visual, CWColormap | CWEventMask | CWBackPixel, &values); /* Create a GC to use for repainting the window */ gc = XCreateGC(dpy, win, 0, NULL); /* Map the window, wait for the Expose events, and paint */ XMapWindow(dpy, win); while (True) { XExposeEvent *e; XNextEvent(dpy, &ev); switch (ev.type) { case Expose: e = (XExposeEvent *) & ev; /* Copy the image to the exposed part of the window */ XPutImage(dpy, win, gc, image, e->x, e->y, e->x, e->y, (e->x + e->width > width ? width - e->x : e->width), (e->y + e->height > height ? height - e->y : e->height)); break; case EnterNotify: /* Mouse is in the window, install its Colormap */ XInstallColormap(dpy, cmap); break; case LeaveNotify: /* Mouse has left the window, uninstall its Colormap */ XUninstallColormap(dpy, cmap); break; } } }