18067a7d5SLisandro Dalcin /* 28067a7d5SLisandro Dalcin Code for getting raster images out of a X image or pixmap 38067a7d5SLisandro Dalcin */ 48067a7d5SLisandro Dalcin 58067a7d5SLisandro Dalcin #include <../src/sys/classes/draw/impls/x/ximpl.h> 68067a7d5SLisandro Dalcin 7dd438433SSatish Balay PETSC_INTERN PetscErrorCode PetscDrawGetImage_X(PetscDraw, unsigned char[PETSC_DRAW_MAXCOLOR][3], unsigned int *, unsigned int *, unsigned char *[]); 88067a7d5SLisandro Dalcin 9d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode PetscArgSortPixVal(const PetscDrawXiPixVal v[PETSC_DRAW_MAXCOLOR], int idx[], int right) 10d71ae5a4SJacob Faibussowitsch { 11f4e3882fSLisandro Dalcin PetscDrawXiPixVal vl; 12f4e3882fSLisandro Dalcin int i, last, tmp; 139371c9d4SSatish Balay #define SWAP(a, b) \ 14*a8f51744SPierre Jolivet do { \ 159371c9d4SSatish Balay tmp = a; \ 169371c9d4SSatish Balay a = b; \ 179371c9d4SSatish Balay b = tmp; \ 18*a8f51744SPierre Jolivet } while (0) 198067a7d5SLisandro Dalcin PetscFunctionBegin; 20f4e3882fSLisandro Dalcin if (right <= 1) { 21f4e3882fSLisandro Dalcin if (right == 1) { 22f4e3882fSLisandro Dalcin if (v[idx[0]] > v[idx[1]]) SWAP(idx[0], idx[1]); 238067a7d5SLisandro Dalcin } 243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 258067a7d5SLisandro Dalcin } 26f4e3882fSLisandro Dalcin SWAP(idx[0], idx[right / 2]); 279371c9d4SSatish Balay vl = v[idx[0]]; 289371c9d4SSatish Balay last = 0; 29f4e3882fSLisandro Dalcin for (i = 1; i <= right; i++) 309371c9d4SSatish Balay if (v[idx[i]] < vl) { 319371c9d4SSatish Balay last++; 329371c9d4SSatish Balay SWAP(idx[last], idx[i]); 339371c9d4SSatish Balay } 34f4e3882fSLisandro Dalcin SWAP(idx[0], idx[last]); 359566063dSJacob Faibussowitsch PetscCall(PetscArgSortPixVal(v, idx, last - 1)); 369566063dSJacob Faibussowitsch PetscCall(PetscArgSortPixVal(v, idx + last + 1, right - (last + 1))); 37f4e3882fSLisandro Dalcin #undef SWAP 383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 398067a7d5SLisandro Dalcin } 408067a7d5SLisandro Dalcin 418067a7d5SLisandro Dalcin /* 428067a7d5SLisandro Dalcin Map a pixel value to PETSc color value (index in the colormap) 438067a7d5SLisandro Dalcin */ 44d71ae5a4SJacob Faibussowitsch static inline int PetscDrawXiPixelToColor(PetscDraw_X *Xwin, const int arg[PETSC_DRAW_MAXCOLOR], PetscDrawXiPixVal pix) 45d71ae5a4SJacob Faibussowitsch { 46f4e3882fSLisandro Dalcin const PetscDrawXiPixVal *cmap = Xwin->cmapping; 47c9bc58c0SBarry Smith int lo, mid, hi = PETSC_DRAW_MAXCOLOR; 48f4e3882fSLisandro Dalcin /* linear search the first few entries */ 49f4e3882fSLisandro Dalcin for (lo = 0; lo < 8; lo++) 509371c9d4SSatish Balay if (pix == cmap[lo]) return lo; 51f4e3882fSLisandro Dalcin /* binary search the remaining entries */ 52f4e3882fSLisandro Dalcin while (hi - lo > 1) { 53f4e3882fSLisandro Dalcin mid = lo + (hi - lo) / 2; 54f4e3882fSLisandro Dalcin if (pix < cmap[arg[mid]]) hi = mid; 55f4e3882fSLisandro Dalcin else lo = mid; 56f4e3882fSLisandro Dalcin } 57f4e3882fSLisandro Dalcin return arg[lo]; 588067a7d5SLisandro Dalcin } 598067a7d5SLisandro Dalcin 60d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawGetImage_X(PetscDraw draw, unsigned char palette[PETSC_DRAW_MAXCOLOR][3], unsigned int *out_w, unsigned int *out_h, unsigned char *out_pixels[]) 61d71ae5a4SJacob Faibussowitsch { 628067a7d5SLisandro Dalcin PetscDraw_X *Xwin = (PetscDraw_X *)draw->data; 638067a7d5SLisandro Dalcin PetscMPIInt rank; 648067a7d5SLisandro Dalcin 658067a7d5SLisandro Dalcin PetscFunctionBegin; 668067a7d5SLisandro Dalcin if (out_w) *out_w = 0; 678067a7d5SLisandro Dalcin if (out_h) *out_h = 0; 688067a7d5SLisandro Dalcin if (out_pixels) *out_pixels = NULL; 699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank)); 708067a7d5SLisandro Dalcin 718067a7d5SLisandro Dalcin /* make sure the X server processed requests from all processes */ 72d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 738067a7d5SLisandro Dalcin XSync(Xwin->disp, True); 74d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)draw))); 768067a7d5SLisandro Dalcin 77f4e3882fSLisandro Dalcin /* only the first process return image data */ 78d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 79dd400576SPatrick Sanan if (rank == 0) { 808067a7d5SLisandro Dalcin Window root; 818067a7d5SLisandro Dalcin XImage *ximage; 82c9bc58c0SBarry Smith int pmap[PETSC_DRAW_MAXCOLOR]; 838067a7d5SLisandro Dalcin unsigned char *pixels = NULL; 848067a7d5SLisandro Dalcin unsigned int w, h, dummy; 858067a7d5SLisandro Dalcin int x, y, p; 86f4e3882fSLisandro Dalcin /* copy colormap palette to the caller */ 879566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(palette, Xwin->cpalette, sizeof(Xwin->cpalette))); 888067a7d5SLisandro Dalcin /* get image out of the drawable */ 898067a7d5SLisandro Dalcin XGetGeometry(Xwin->disp, PetscDrawXiDrawable(Xwin), &root, &x, &y, &w, &h, &dummy, &dummy); 908067a7d5SLisandro Dalcin ximage = XGetImage(Xwin->disp, PetscDrawXiDrawable(Xwin), 0, 0, w, h, AllPlanes, ZPixmap); 9128b400f6SJacob Faibussowitsch PetscCheck(ximage, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot XGetImage()"); 92f4e3882fSLisandro Dalcin /* build indirect sort permutation (a.k.a argsort) of the color -> pixel mapping */ 93c9bc58c0SBarry Smith for (p = 0; p < PETSC_DRAW_MAXCOLOR; p++) pmap[p] = p; /* identity permutation */ 949566063dSJacob Faibussowitsch PetscCall(PetscArgSortPixVal(Xwin->cmapping, pmap, 255)); 95f4e3882fSLisandro Dalcin /* extract pixel values out of the image and map them to color indices */ 969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(w * h, &pixels)); 978067a7d5SLisandro Dalcin for (p = 0, y = 0; y < (int)h; y++) 98f4e3882fSLisandro Dalcin for (x = 0; x < (int)w; x++) { 99f4e3882fSLisandro Dalcin PetscDrawXiPixVal pix = XGetPixel(ximage, x, y); 100f4e3882fSLisandro Dalcin pixels[p++] = (unsigned char)PetscDrawXiPixelToColor(Xwin, pmap, pix); 101f4e3882fSLisandro Dalcin } 1028067a7d5SLisandro Dalcin XDestroyImage(ximage); 1038067a7d5SLisandro Dalcin *out_w = w; 1048067a7d5SLisandro Dalcin *out_h = h; 1058067a7d5SLisandro Dalcin *out_pixels = pixels; 1068067a7d5SLisandro Dalcin } 107d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 1083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1098067a7d5SLisandro Dalcin } 110