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