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