home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / doc / tutorials / visuals / xsd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-12-23  |  6.6 KB  |  216 lines

  1. #include <X11/Xlib.h>
  2. #include <stdio.h>
  3. #define    max(a,b)    ((a) > (b) ? (a) : (b))
  4. #define    min(a,b)    ((a) < (b) ? (a) : (b))
  5.  
  6. Display    *dpy;        /* X server we're talking to */
  7. int dumpw, dumph;    /* Size of the "specified rectangle" */
  8.  
  9. /*
  10.  *  There will be one of these for each Colormap we find
  11.  */
  12. struct cmp {
  13.     struct cmp        *next;        /* Link in chain */
  14.     Colormap        cmap;        /* The Colormap ID */
  15.     unsigned long    allocated, used;/* Size & usage of inUse */
  16.     XColor        *inUse;        /* Array of in-use colors */
  17. };
  18. struct cmp *inUse;    /* The list of Colormaps we found */
  19. int numColor = 0;    /* Upper bound on number of distinct RGB values */
  20.  
  21. /*
  22.  *  There will be one of these for each pixel in the rectangle
  23.  */
  24. struct pxl {
  25.     struct cmp        *pCmap;        /* The colormap for this pixel */
  26.     unsigned long    pixel;        /* The pixel value at this pixel */
  27. };
  28. struct pxl *Map;    /* The map representing the rectangle */
  29. #define FindPixel(x,y) ((Map+((y)*dumpw))+(x))
  30.  
  31. /*
  32.  *  Find (and create if necessary) a struct cmp for this Colormap
  33.  */
  34. struct cmp *
  35. FindColormap(cmap)
  36.     Colormap    cmap;
  37. {
  38.     register struct cmp *pCmap;
  39.  
  40.     /*  If we've seen this Colormap before,  return its struct cmp */
  41.     for (pCmap = inUse;  pCmap; pCmap = pCmap->next)
  42.     if (cmap == pCmap->cmap)
  43.         return (pCmap);
  44.     /* First time, so create a new struct cmp, link it and return it */
  45.     pCmap = (struct cmp *) calloc(sizeof (struct cmp), 1);
  46.     pCmap->next = inUse;
  47.     pCmap->cmap  = cmap;
  48.     inUse = pCmap;
  49.     return (pCmap);
  50. }
  51.  
  52. /*
  53.  *  Record this pixel value as being in use in its Colormap
  54.  */
  55. void
  56. RegisterPixel(pixel, pCmap)
  57.     unsigned long    pixel;
  58.     struct cmp        *pCmap;
  59. {
  60.     register unsigned long i = pCmap->used;
  61.  
  62.     /*  If the pixel value is already known,  do nothing */
  63.     while (i)
  64.     if (pixel == pCmap->inUse[--i].pixel)
  65.         return;
  66.     /*  This is the first time we've seen this pixel value */
  67.     if (pCmap->used >= pCmap->allocated) {
  68.     /*  Need to expand or create the inUse array */
  69.     pCmap->allocated = (pCmap->allocated * 2) + 10;
  70.     pCmap->inUse = (XColor *)(pCmap->inUse ?
  71.             realloc(pCmap->inUse,
  72.                 pCmap->allocated * sizeof (XColor)) :
  73.             malloc(pCmap->allocated * sizeof (XColor)));
  74.     }
  75.     /*  Now we have space to store the XColor, use QueryColor to get RGB */
  76.     pCmap->inUse[pCmap->used].pixel = pixel;
  77.     XQueryColor(dpy, pCmap->cmap, &pCmap->inUse[pCmap->used]);
  78.     numColor++;
  79.     pCmap->used++;
  80. }
  81.  
  82. /*
  83.  *  This gets called once for each window we find as we walk down the tree
  84.  */
  85. DoWindow(w, xo, yo, x, y, wi, hi)
  86.     Window    w;
  87.     int        xo, yo;    /* Parent's origin in root space */
  88.     int        x, y;    /* Top-left of rectangle in root space */
  89.     int        wi, hi;    /* Size of rectangle */
  90. {
  91.     XWindowAttributes    xwa;    /* Place to return the window's attributes */
  92.     XImage        *xim;    /* Image to store window's pixels */
  93.     int            width, height, x1, y1, xi, yi;
  94.     Window        root, parent, *children;
  95.     int            nchild, n;
  96.     struct cmp        *pCmap;
  97.  
  98.     /*  Get the attributes of this window,  and locate its struct cmp */
  99.     if (!XGetWindowAttributes(dpy, w, &xwa) || xwa.map_state != IsViewable)
  100.     return;
  101.     pCmap = FindColormap(xwa.colormap);
  102.     /* Compute top-left of image in root space */
  103.     x1 = max(x, xwa.x+xo);
  104.     y1 = max(y, xwa.y+yo);
  105.     width = min(x+wi, xwa.x + xwa.width + 2*xwa.border_width + xo) - x1;
  106.     height = min(y+hi, xwa.y + xwa.height + 2*xwa.border_width + yo) - y1;
  107.     if (width <= 0 || height <= 0)
  108.     return;
  109.     /*  Use GetImage to get the pixel values for the rectangle */
  110.     if (!(xim = XGetImage(dpy, w, x1-xwa.border_width-xwa.x-xo,
  111.               y1-xwa.border_width-xwa.y-yo, width, height,
  112.               (~0), ZPixmap)))
  113.     return;
  114.     /*  For each pixel in the returned image */
  115.     for (yi = 0; yi < height; yi++)
  116.     for (xi = 0; xi < width; xi++) {
  117.         register struct pxl *pPxl = FindPixel(xi+x1, yi+y1);
  118.  
  119.         /*  Label the pixel in the map  with this window's Colormap */
  120.         pPxl->pCmap = pCmap;
  121.         /*  And with its pixel value */
  122.         pPxl->pixel = XGetPixel(xim, xi, yi);
  123.         RegisterPixel(pPxl->pixel, pCmap);
  124.     }
  125.     /*  Free the space for the image */
  126.     XDestroyImage(xim);
  127.     /*  Find the children of this window, in back-to-front order */
  128.     if (XQueryTree(dpy, w, &root, &parent, &children, &nchild)) {
  129.     for (n = 0; n < nchild; n++) {
  130.         /*  Process each of the child windows recursively */
  131.         DoWindow(children[n], xo + xwa.x + xwa.border_width,
  132.              yo + xwa.y + xwa.border_width, x1, y1, width, height);
  133.     }
  134.     /*  Free the list of children */
  135.     if (nchild > 0)
  136.         XFree(children);
  137.     }
  138.     return;
  139. }
  140.  
  141. /*
  142.  *  Return the XColor structure for the pixel at [x,y] in the map
  143.  */
  144. XColor *
  145. FindColor(x, y)
  146.     int        x, y;
  147. {
  148.     struct pxl    *pPxl = FindPixel(x, y);    /* Find the struct pxl */
  149.     struct cmp    *pCmp = pPxl->pCmap;        /* And the struct cmp */
  150.     int        i;
  151.  
  152.     /*  Scan the in-use array for this colormap for the pixel value */
  153.     for (i = 0; i < pCmp->used; i++)
  154.     if (pPxl->pixel == pCmp->inUse[i].pixel)
  155.         return (&(pCmp->inUse[i]));
  156.     return (NULL);
  157. }
  158.  
  159. /*
  160.  *  Write the representation of the rectangle to stdout
  161.  */
  162. DoOutput(x, y, w, h)
  163.     int        x, y, w, h;
  164. {
  165.     int        xi, yi;
  166.  
  167.     /*  Write the width,  height,  and number of colors */
  168.     fwrite(&w, sizeof (int), 1, stdout);
  169.     fwrite(&h, sizeof (int), 1, stdout);
  170.     fwrite(&numColor, sizeof (int), 1, stdout);
  171.     /*  For each pixel in the image */
  172.     for (yi = 0; yi < h; yi++)
  173.     for (xi = 0; xi < w; xi++) {
  174.         XColor    *color = FindColor(x + xi, y + yi);
  175.  
  176.         /*  Write the R, G & B values for this pixel */
  177.         fwrite(&(color->red), sizeof (unsigned short), 1, stdout);
  178.         fwrite(&(color->green), sizeof (unsigned short), 1, stdout);
  179.         fwrite(&(color->blue), sizeof (unsigned short), 1, stdout);
  180.     }
  181. }
  182.  
  183. main(argc, argv)
  184.     int        argc;
  185.     char    **argv;
  186. {
  187.     int        scrn;
  188.  
  189.     /*  Try to connect to the server */
  190.     if ((dpy = XOpenDisplay(NULL)) == (Display *) 0) {
  191.     fprintf(stderr, "Can't open display\n");
  192.     exit(1);
  193.     }
  194.     /*  Dump the specified part of the default screen */
  195.     scrn = DefaultScreen(dpy);
  196.     if (argc > 1)
  197.     dumpw = atoi(argv[1]);
  198.     else
  199.         dumpw = DisplayWidth(dpy, scrn);
  200.     if (argc > 2)
  201.     dumph = atoi(argv[2]);
  202.     else
  203.         dumph = DisplayHeight(dpy, scrn);
  204.     /*  Create the map with one struct pxl per pixel */
  205.     Map = (struct pxl *) calloc(sizeof (struct pxl), dumpw * dumph);
  206.     /*  Grab the server so things don't change under our feet */
  207.     XGrabServer(dpy);
  208.     /*  Recursively build the map */
  209.     DoWindow(RootWindow(dpy, scrn), 0, 0, 0, 0, dumpw, dumph);
  210.     /*  Finished reading things from the server - let it go */
  211.     XUngrabServer(dpy);
  212.     /*  Write the RGB representation of the rectangle to stdout */
  213.     DoOutput(0, 0, dumpw, dumph);
  214.     exit(0);
  215. }
  216.