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
PetscArgSortPixVal(const PetscDrawXiPixVal v[PETSC_DRAW_MAXCOLOR],int idx[],int right)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 */
PetscDrawXiPixelToColor(PetscDraw_X * Xwin,const int arg[PETSC_DRAW_MAXCOLOR],PetscDrawXiPixVal pix)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
PetscDrawGetImage_X(PetscDraw draw,unsigned char palette[PETSC_DRAW_MAXCOLOR][3],unsigned int * out_w,unsigned int * out_h,unsigned char * out_pixels[])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