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