Actual source code: ximage.c

  1: /*
  2:     Code for getting raster images out of a X image or pixmap
  3: */

  5: #include <../src/sys/classes/draw/impls/x/ximpl.h>

  7: PETSC_INTERN PetscErrorCode PetscDrawGetImage_X(PetscDraw, unsigned char[PETSC_DRAW_MAXCOLOR][3], unsigned int *, unsigned int *, unsigned char *[]);

  9: static inline PetscErrorCode PetscArgSortPixVal(const PetscDrawXiPixVal v[PETSC_DRAW_MAXCOLOR], int idx[], int right)
 10: {
 11:   PetscDrawXiPixVal vl;
 12:   int               i, last, tmp;
 13: #define SWAP(a, b) \
 14:   { \
 15:     tmp = a; \
 16:     a   = b; \
 17:     b   = tmp; \
 18:   }
 19:   if (right <= 1) {
 20:     if (right == 1) {
 21:       if (v[idx[0]] > v[idx[1]]) SWAP(idx[0], idx[1]);
 22:     }
 23:     return 0;
 24:   }
 25:   SWAP(idx[0], idx[right / 2]);
 26:   vl   = v[idx[0]];
 27:   last = 0;
 28:   for (i = 1; i <= right; i++)
 29:     if (v[idx[i]] < vl) {
 30:       last++;
 31:       SWAP(idx[last], idx[i]);
 32:     }
 33:   SWAP(idx[0], idx[last]);
 34:   PetscArgSortPixVal(v, idx, last - 1);
 35:   PetscArgSortPixVal(v, idx + last + 1, right - (last + 1));
 36: #undef SWAP
 37:   return 0;
 38: }

 40: /*
 41:    Map a pixel value to PETSc color value (index in the colormap)
 42: */
 43: static inline int PetscDrawXiPixelToColor(PetscDraw_X *Xwin, const int arg[PETSC_DRAW_MAXCOLOR], PetscDrawXiPixVal pix)
 44: {
 45:   const PetscDrawXiPixVal *cmap = Xwin->cmapping;
 46:   int                      lo, mid, hi = PETSC_DRAW_MAXCOLOR;
 47:   /* linear search the first few entries */
 48:   for (lo = 0; lo < 8; lo++)
 49:     if (pix == cmap[lo]) return lo;
 50:   /* binary search the remaining entries */
 51:   while (hi - lo > 1) {
 52:     mid = lo + (hi - lo) / 2;
 53:     if (pix < cmap[arg[mid]]) hi = mid;
 54:     else lo = mid;
 55:   }
 56:   return arg[lo];
 57: }

 59: PetscErrorCode PetscDrawGetImage_X(PetscDraw draw, unsigned char palette[PETSC_DRAW_MAXCOLOR][3], unsigned int *out_w, unsigned int *out_h, unsigned char *out_pixels[])
 60: {
 61:   PetscDraw_X *Xwin = (PetscDraw_X *)draw->data;
 62:   PetscMPIInt  rank;

 64:   if (out_w) *out_w = 0;
 65:   if (out_h) *out_h = 0;
 66:   if (out_pixels) *out_pixels = NULL;
 67:   MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank);

 69:   /* make sure the X server processed requests from all processes */
 70:   PetscDrawCollectiveBegin(draw);
 71:   XSync(Xwin->disp, True);
 72:   PetscDrawCollectiveEnd(draw);
 73:   MPI_Barrier(PetscObjectComm((PetscObject)draw));

 75:   /* only the first process return image data */
 76:   PetscDrawCollectiveBegin(draw);
 77:   if (rank == 0) {
 78:     Window         root;
 79:     XImage        *ximage;
 80:     int            pmap[PETSC_DRAW_MAXCOLOR];
 81:     unsigned char *pixels = NULL;
 82:     unsigned int   w, h, dummy;
 83:     int            x, y, p;
 84:     /* copy colormap palette to the caller */
 85:     PetscMemcpy(palette, Xwin->cpalette, sizeof(Xwin->cpalette));
 86:     /* get image out of the drawable */
 87:     XGetGeometry(Xwin->disp, PetscDrawXiDrawable(Xwin), &root, &x, &y, &w, &h, &dummy, &dummy);
 88:     ximage = XGetImage(Xwin->disp, PetscDrawXiDrawable(Xwin), 0, 0, w, h, AllPlanes, ZPixmap);
 90:     /* build indirect sort permutation (a.k.a argsort) of the color -> pixel mapping */
 91:     for (p = 0; p < PETSC_DRAW_MAXCOLOR; p++) pmap[p] = p; /* identity permutation */
 92:     PetscArgSortPixVal(Xwin->cmapping, pmap, 255);
 93:     /* extract pixel values out of the image and map them to color indices */
 94:     PetscMalloc1(w * h, &pixels);
 95:     for (p = 0, y = 0; y < (int)h; y++)
 96:       for (x = 0; x < (int)w; x++) {
 97:         PetscDrawXiPixVal pix = XGetPixel(ximage, x, y);
 98:         pixels[p++]           = (unsigned char)PetscDrawXiPixelToColor(Xwin, pmap, pix);
 99:       }
100:     XDestroyImage(ximage);
101:     *out_w      = w;
102:     *out_h      = h;
103:     *out_pixels = pixels;
104:   }
105:   PetscDrawCollectiveEnd(draw);
106:   return 0;
107: }