xref: /petsc/src/sys/classes/draw/impls/x/ximage.c (revision c3e4dd79e17d3f0a51a524340fae4661630fd09e)
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 
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) {tmp=a;a=b;b=tmp;}
14   PetscFunctionBegin;
15   if (right <= 1) {
16     if (right == 1) {
17       if (v[idx[0]] > v[idx[1]]) SWAP(idx[0],idx[1]);
18     }
19     PetscFunctionReturn(0);
20   }
21   SWAP(idx[0],idx[right/2]);
22   vl = v[idx[0]]; last = 0;
23   for (i=1; i<=right; i++)
24     if (v[idx[i]] < vl) {last++; SWAP(idx[last],idx[i]);}
25   SWAP(idx[0],idx[last]);
26   PetscCall(PetscArgSortPixVal(v,idx,last-1));
27   PetscCall(PetscArgSortPixVal(v,idx+last+1,right-(last+1)));
28 # undef SWAP
29   PetscFunctionReturn(0);
30 }
31 
32 /*
33    Map a pixel value to PETSc color value (index in the colormap)
34 */
35 static inline int PetscDrawXiPixelToColor(PetscDraw_X *Xwin,const int arg[PETSC_DRAW_MAXCOLOR],PetscDrawXiPixVal pix)
36 {
37   const PetscDrawXiPixVal *cmap = Xwin->cmapping;
38   int                     lo, mid, hi = PETSC_DRAW_MAXCOLOR;
39   /* linear search the first few entries */
40   for (lo=0; lo<8; lo++)
41     if (pix == cmap[lo])
42       return lo;
43   /* binary search the remaining entries */
44   while (hi - lo > 1) {
45     mid = lo + (hi - lo)/2;
46     if (pix < cmap[arg[mid]]) hi = mid;
47     else                      lo = mid;
48   }
49   return arg[lo];
50 }
51 
52 PetscErrorCode PetscDrawGetImage_X(PetscDraw draw,unsigned char palette[PETSC_DRAW_MAXCOLOR][3],unsigned int *out_w,unsigned int *out_h,unsigned char *out_pixels[])
53 {
54   PetscDraw_X      *Xwin = (PetscDraw_X*)draw->data;
55   PetscMPIInt      rank;
56 
57   PetscFunctionBegin;
58   if (out_w)      *out_w      = 0;
59   if (out_h)      *out_h      = 0;
60   if (out_pixels) *out_pixels = NULL;
61   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank));
62 
63   /* make sure the X server processed requests from all processes */
64   PetscDrawCollectiveBegin(draw);
65   XSync(Xwin->disp,True);
66   PetscDrawCollectiveEnd(draw);
67   PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)draw)));
68 
69   /* only the first process return image data */
70   PetscDrawCollectiveBegin(draw);
71   if (rank == 0) {
72     Window        root;
73     XImage        *ximage;
74     int           pmap[PETSC_DRAW_MAXCOLOR];
75     unsigned char *pixels = NULL;
76     unsigned int  w,h,dummy;
77     int           x,y,p;
78     /* copy colormap palette to the caller */
79     PetscCall(PetscMemcpy(palette,Xwin->cpalette,sizeof(Xwin->cpalette)));
80     /* get image out of the drawable */
81     XGetGeometry(Xwin->disp,PetscDrawXiDrawable(Xwin),&root,&x,&y,&w,&h,&dummy,&dummy);
82     ximage = XGetImage(Xwin->disp,PetscDrawXiDrawable(Xwin),0,0,w,h,AllPlanes,ZPixmap);
83     PetscCheck(ximage,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot XGetImage()");
84     /* build indirect sort permutation (a.k.a argsort) of the color -> pixel mapping */
85     for (p=0; p<PETSC_DRAW_MAXCOLOR; p++) pmap[p] = p; /* identity permutation */
86     PetscCall(PetscArgSortPixVal(Xwin->cmapping,pmap,255));
87     /* extract pixel values out of the image and map them to color indices */
88     PetscCall(PetscMalloc1(w*h,&pixels));
89     for (p=0,y=0; y<(int)h; y++)
90       for (x=0; x<(int)w; x++) {
91         PetscDrawXiPixVal pix = XGetPixel(ximage,x,y);
92         pixels[p++] = (unsigned char)PetscDrawXiPixelToColor(Xwin,pmap,pix);
93       }
94     XDestroyImage(ximage);
95     *out_w      = w;
96     *out_h      = h;
97     *out_pixels = pixels;
98   }
99   PetscDrawCollectiveEnd(draw);
100   PetscFunctionReturn(0);
101 }
102