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 CHKERRQ(PetscArgSortPixVal(v,idx,last-1)); 27 CHKERRQ(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 PetscErrorCode ierr; 57 58 PetscFunctionBegin; 59 if (out_w) *out_w = 0; 60 if (out_h) *out_h = 0; 61 if (out_pixels) *out_pixels = NULL; 62 CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank)); 63 64 /* make sure the X server processed requests from all processes */ 65 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 66 XSync(Xwin->disp,True); 67 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 68 CHKERRMPI(MPI_Barrier(PetscObjectComm((PetscObject)draw))); 69 70 /* only the first process return image data */ 71 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 72 if (rank == 0) { 73 Window root; 74 XImage *ximage; 75 int pmap[PETSC_DRAW_MAXCOLOR]; 76 unsigned char *pixels = NULL; 77 unsigned int w,h,dummy; 78 int x,y,p; 79 /* copy colormap palette to the caller */ 80 CHKERRQ(PetscMemcpy(palette,Xwin->cpalette,sizeof(Xwin->cpalette))); 81 /* get image out of the drawable */ 82 XGetGeometry(Xwin->disp,PetscDrawXiDrawable(Xwin),&root,&x,&y,&w,&h,&dummy,&dummy); 83 ximage = XGetImage(Xwin->disp,PetscDrawXiDrawable(Xwin),0,0,w,h,AllPlanes,ZPixmap); 84 PetscCheckFalse(!ximage,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot XGetImage()"); 85 /* build indirect sort permutation (a.k.a argsort) of the color -> pixel mapping */ 86 for (p=0; p<PETSC_DRAW_MAXCOLOR; p++) pmap[p] = p; /* identity permutation */ 87 CHKERRQ(PetscArgSortPixVal(Xwin->cmapping,pmap,255)); 88 /* extract pixel values out of the image and map them to color indices */ 89 CHKERRQ(PetscMalloc1(w*h,&pixels)); 90 for (p=0,y=0; y<(int)h; y++) 91 for (x=0; x<(int)w; x++) { 92 PetscDrawXiPixVal pix = XGetPixel(ximage,x,y); 93 pixels[p++] = (unsigned char)PetscDrawXiPixelToColor(Xwin,pmap,pix); 94 } 95 XDestroyImage(ximage); 96 *out_w = w; 97 *out_h = h; 98 *out_pixels = pixels; 99 } 100 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 101 PetscFunctionReturn(0); 102 } 103