xref: /petsc/src/sys/classes/draw/impls/x/ximage.c (revision cf9512e468810271e605c7107b28f68f448f0948)
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