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