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 { 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 } 40 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 } 59 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; 64 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)); 70 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))); 76 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 } 110