Actual source code: ximage.c
1: /*
2: Code for getting raster images out of a X image or pixmap
3: */
5: #include <../src/sys/classes/draw/impls/x/ximpl.h>
7: PETSC_INTERN PetscErrorCode PetscDrawGetImage_X(PetscDraw, unsigned char[PETSC_DRAW_MAXCOLOR][3], unsigned int *, unsigned int *, unsigned char *[]);
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: }
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: }
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;
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));
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)));
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: }