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:   do { \
 15:     tmp = a; \
 16:     a   = b; \
 17:     b   = tmp; \
 18:   } while (0)
 19:   PetscFunctionBegin;
 20:   if (right <= 1) {
 21:     if (right == 1) {
 22:       if (v[idx[0]] > v[idx[1]]) SWAP(idx[0], idx[1]);
 23:     }
 24:     PetscFunctionReturn(PETSC_SUCCESS);
 25:   }
 26:   SWAP(idx[0], idx[right / 2]);
 27:   vl   = v[idx[0]];
 28:   last = 0;
 29:   for (i = 1; i <= right; i++)
 30:     if (v[idx[i]] < vl) {
 31:       last++;
 32:       SWAP(idx[last], idx[i]);
 33:     }
 34:   SWAP(idx[0], idx[last]);
 35:   PetscCall(PetscArgSortPixVal(v, idx, last - 1));
 36:   PetscCall(PetscArgSortPixVal(v, idx + last + 1, right - (last + 1)));
 37: #undef SWAP
 38:   PetscFunctionReturn(PETSC_SUCCESS);
 39: }

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

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

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

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

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