1 /* 2 Code for getting raster images out of a X image or pixmap 3 */ 4 5 #include <../src/sys/classes/draw/impls/x/ximpl.h> 6 7 PETSC_INTERN PetscErrorCode PetscDrawGetImage_X(PetscDraw, unsigned char[PETSC_DRAW_MAXCOLOR][3], unsigned int *, unsigned int *, unsigned char *[]); 8 9 static inline PetscErrorCode PetscArgSortPixVal(const PetscDrawXiPixVal v[PETSC_DRAW_MAXCOLOR], int idx[], int right) { 10 PetscDrawXiPixVal vl; 11 int i, last, tmp; 12 #define SWAP(a, b) \ 13 { \ 14 tmp = a; \ 15 a = b; \ 16 b = tmp; \ 17 } 18 PetscFunctionBegin; 19 if (right <= 1) { 20 if (right == 1) { 21 if (v[idx[0]] > v[idx[1]]) SWAP(idx[0], idx[1]); 22 } 23 PetscFunctionReturn(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 PetscCall(PetscArgSortPixVal(v, idx, last - 1)); 35 PetscCall(PetscArgSortPixVal(v, idx + last + 1, right - (last + 1))); 36 #undef SWAP 37 PetscFunctionReturn(0); 38 } 39 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 const PetscDrawXiPixVal *cmap = Xwin->cmapping; 45 int lo, mid, hi = PETSC_DRAW_MAXCOLOR; 46 /* linear search the first few entries */ 47 for (lo = 0; lo < 8; lo++) 48 if (pix == cmap[lo]) return lo; 49 /* binary search the remaining entries */ 50 while (hi - lo > 1) { 51 mid = lo + (hi - lo) / 2; 52 if (pix < cmap[arg[mid]]) hi = mid; 53 else lo = mid; 54 } 55 return arg[lo]; 56 } 57 58 PetscErrorCode PetscDrawGetImage_X(PetscDraw draw, unsigned char palette[PETSC_DRAW_MAXCOLOR][3], unsigned int *out_w, unsigned int *out_h, unsigned char *out_pixels[]) { 59 PetscDraw_X *Xwin = (PetscDraw_X *)draw->data; 60 PetscMPIInt rank; 61 62 PetscFunctionBegin; 63 if (out_w) *out_w = 0; 64 if (out_h) *out_h = 0; 65 if (out_pixels) *out_pixels = NULL; 66 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank)); 67 68 /* make sure the X server processed requests from all processes */ 69 PetscDrawCollectiveBegin(draw); 70 XSync(Xwin->disp, True); 71 PetscDrawCollectiveEnd(draw); 72 PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)draw))); 73 74 /* only the first process return image data */ 75 PetscDrawCollectiveBegin(draw); 76 if (rank == 0) { 77 Window root; 78 XImage *ximage; 79 int pmap[PETSC_DRAW_MAXCOLOR]; 80 unsigned char *pixels = NULL; 81 unsigned int w, h, dummy; 82 int x, y, p; 83 /* copy colormap palette to the caller */ 84 PetscCall(PetscMemcpy(palette, Xwin->cpalette, sizeof(Xwin->cpalette))); 85 /* get image out of the drawable */ 86 XGetGeometry(Xwin->disp, PetscDrawXiDrawable(Xwin), &root, &x, &y, &w, &h, &dummy, &dummy); 87 ximage = XGetImage(Xwin->disp, PetscDrawXiDrawable(Xwin), 0, 0, w, h, AllPlanes, ZPixmap); 88 PetscCheck(ximage, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot XGetImage()"); 89 /* build indirect sort permutation (a.k.a argsort) of the color -> pixel mapping */ 90 for (p = 0; p < PETSC_DRAW_MAXCOLOR; p++) pmap[p] = p; /* identity permutation */ 91 PetscCall(PetscArgSortPixVal(Xwin->cmapping, pmap, 255)); 92 /* extract pixel values out of the image and map them to color indices */ 93 PetscCall(PetscMalloc1(w * h, &pixels)); 94 for (p = 0, y = 0; y < (int)h; y++) 95 for (x = 0; x < (int)w; x++) { 96 PetscDrawXiPixVal pix = XGetPixel(ximage, x, y); 97 pixels[p++] = (unsigned char)PetscDrawXiPixelToColor(Xwin, pmap, pix); 98 } 99 XDestroyImage(ximage); 100 *out_w = w; 101 *out_h = h; 102 *out_pixels = pixels; 103 } 104 PetscDrawCollectiveEnd(draw); 105 PetscFunctionReturn(0); 106 } 107