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