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