xref: /petsc/src/sys/classes/draw/impls/x/ximage.c (revision f4e3882f77ff5617a1fcee8d8eef4db0123f10fc)
18067a7d5SLisandro Dalcin /*
28067a7d5SLisandro Dalcin     Code for getting raster images out of a X image or pixmap
38067a7d5SLisandro Dalcin */
48067a7d5SLisandro Dalcin 
58067a7d5SLisandro Dalcin #include <../src/sys/classes/draw/impls/x/ximpl.h>
68067a7d5SLisandro Dalcin 
78067a7d5SLisandro Dalcin PETSC_INTERN PetscErrorCode PetscDrawGetImage_X(PetscDraw,unsigned char[][3],unsigned int*,unsigned int*,unsigned char*[]);
88067a7d5SLisandro Dalcin 
98067a7d5SLisandro Dalcin 
10*f4e3882fSLisandro Dalcin #undef __FUNCT__
11*f4e3882fSLisandro Dalcin #define __FUNCT__ "PetscArgSortPixVal"
12*f4e3882fSLisandro Dalcin PETSC_STATIC_INLINE PetscErrorCode PetscArgSortPixVal(const PetscDrawXiPixVal v[256],int idx[],int right)
13*f4e3882fSLisandro Dalcin {
14*f4e3882fSLisandro Dalcin   PetscDrawXiPixVal vl;
15*f4e3882fSLisandro Dalcin   int               i,last,tmp;
16*f4e3882fSLisandro Dalcin   PetscErrorCode    ierr;
17*f4e3882fSLisandro Dalcin # define            SWAP(a,b) {tmp=a;a=b;b=tmp;}
188067a7d5SLisandro Dalcin   PetscFunctionBegin;
19*f4e3882fSLisandro Dalcin   if (right <= 1) {
20*f4e3882fSLisandro Dalcin     if (right == 1) {
21*f4e3882fSLisandro Dalcin       if (v[idx[0]] > v[idx[1]]) SWAP(idx[0],idx[1]);
228067a7d5SLisandro Dalcin     }
23*f4e3882fSLisandro Dalcin     PetscFunctionReturn(0);
248067a7d5SLisandro Dalcin   }
25*f4e3882fSLisandro Dalcin   SWAP(idx[0],idx[right/2]);
26*f4e3882fSLisandro Dalcin   vl = v[idx[0]]; last = 0;
27*f4e3882fSLisandro Dalcin   for (i=1; i<=right; i++)
28*f4e3882fSLisandro Dalcin     if (v[idx[i]] < vl) {last++; SWAP(idx[last],idx[i]);}
29*f4e3882fSLisandro Dalcin   SWAP(idx[0],idx[last]);
30*f4e3882fSLisandro Dalcin   ierr = PetscArgSortPixVal(v,idx,last-1);CHKERRQ(ierr);
31*f4e3882fSLisandro Dalcin   ierr = PetscArgSortPixVal(v,idx+last+1,right-(last+1));CHKERRQ(ierr);
32*f4e3882fSLisandro Dalcin # undef SWAP
338067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
348067a7d5SLisandro Dalcin }
358067a7d5SLisandro Dalcin 
368067a7d5SLisandro Dalcin /*
378067a7d5SLisandro Dalcin    Map a pixel value to PETSc color value (index in the colormap)
388067a7d5SLisandro Dalcin */
398067a7d5SLisandro Dalcin #undef __FUNCT__
40*f4e3882fSLisandro Dalcin #define __FUNCT__ "PetscFindPixVal"
41*f4e3882fSLisandro Dalcin PETSC_STATIC_INLINE int PetscDrawXiPixelToColor(PetscDraw_X *Xwin,const int arg[256],PetscDrawXiPixVal pix)
428067a7d5SLisandro Dalcin {
43*f4e3882fSLisandro Dalcin   const PetscDrawXiPixVal *cmap = Xwin->cmapping;
44*f4e3882fSLisandro Dalcin   int                     lo, mid, hi = 256;
45*f4e3882fSLisandro Dalcin   /* linear search the first few entries */
46*f4e3882fSLisandro Dalcin   for (lo=0; lo<8; lo++)
47*f4e3882fSLisandro Dalcin     if (pix == cmap[lo])
48*f4e3882fSLisandro Dalcin       return lo;
49*f4e3882fSLisandro Dalcin   /* binary search the remaining entries */
50*f4e3882fSLisandro Dalcin   while (hi - lo > 1) {
51*f4e3882fSLisandro Dalcin     mid = lo + (hi - lo)/2;
52*f4e3882fSLisandro Dalcin     if (pix < cmap[arg[mid]]) hi = mid;
53*f4e3882fSLisandro Dalcin     else                      lo = mid;
54*f4e3882fSLisandro Dalcin   }
55*f4e3882fSLisandro Dalcin   return arg[lo];
568067a7d5SLisandro Dalcin }
578067a7d5SLisandro Dalcin 
588067a7d5SLisandro Dalcin #undef __FUNCT__
598067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawGetImage_X"
608067a7d5SLisandro Dalcin PetscErrorCode PetscDrawGetImage_X(PetscDraw draw,unsigned char palette[256][3],unsigned int *out_w,unsigned int *out_h,unsigned char *out_pixels[])
618067a7d5SLisandro Dalcin {
628067a7d5SLisandro Dalcin   PetscDraw_X      *Xwin = (PetscDraw_X*)draw->data;
638067a7d5SLisandro Dalcin   PetscMPIInt      rank;
648067a7d5SLisandro Dalcin   PetscErrorCode   ierr;
658067a7d5SLisandro Dalcin 
668067a7d5SLisandro Dalcin   PetscFunctionBegin;
678067a7d5SLisandro Dalcin   if (out_w)      *out_w      = 0;
688067a7d5SLisandro Dalcin   if (out_h)      *out_h      = 0;
698067a7d5SLisandro Dalcin   if (out_pixels) *out_pixels = NULL;
708067a7d5SLisandro Dalcin   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
718067a7d5SLisandro Dalcin 
728067a7d5SLisandro Dalcin   /* make sure the X server processed requests from all processes */
738067a7d5SLisandro Dalcin   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
748067a7d5SLisandro Dalcin   XSync(Xwin->disp,True);
758067a7d5SLisandro Dalcin   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
768067a7d5SLisandro Dalcin   ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
778067a7d5SLisandro Dalcin 
78*f4e3882fSLisandro Dalcin   /* only the first process return image data */
798067a7d5SLisandro Dalcin   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
808067a7d5SLisandro Dalcin   if (!rank) {
818067a7d5SLisandro Dalcin     Window        root;
828067a7d5SLisandro Dalcin     XImage        *ximage;
83*f4e3882fSLisandro Dalcin     int           pmap[256];
848067a7d5SLisandro Dalcin     unsigned char *pixels = NULL;
858067a7d5SLisandro Dalcin     unsigned int  w,h,dummy;
868067a7d5SLisandro Dalcin     int           x,y,p;
87*f4e3882fSLisandro Dalcin     /* copy colormap palette to the caller */
88*f4e3882fSLisandro Dalcin     ierr = PetscMemcpy(palette,Xwin->cpalette,sizeof(Xwin->cpalette));CHKERRQ(ierr);
898067a7d5SLisandro Dalcin     /* get image out of the drawable */
908067a7d5SLisandro Dalcin     XGetGeometry(Xwin->disp,PetscDrawXiDrawable(Xwin),&root,&x,&y,&w,&h,&dummy,&dummy);
918067a7d5SLisandro Dalcin     ximage = XGetImage(Xwin->disp,PetscDrawXiDrawable(Xwin),0,0,w,h,AllPlanes,ZPixmap);
928067a7d5SLisandro Dalcin     if (!ximage) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot XGetImage()");
93*f4e3882fSLisandro Dalcin     /* build indirect sort permutation (a.k.a argsort) of the color -> pixel mapping */
94*f4e3882fSLisandro Dalcin     for (p=0; p<256; p++) pmap[p] = p; /* identity permutation */
95*f4e3882fSLisandro Dalcin     ierr = PetscArgSortPixVal(Xwin->cmapping,pmap,255);CHKERRQ(ierr);
96*f4e3882fSLisandro Dalcin     /* extract pixel values out of the image and map them to color indices */
978067a7d5SLisandro Dalcin     ierr = PetscMalloc1(w*h,&pixels);CHKERRQ(ierr);
988067a7d5SLisandro Dalcin     for (p=0,y=0; y<(int)h; y++)
99*f4e3882fSLisandro Dalcin       for (x=0; x<(int)w; x++) {
100*f4e3882fSLisandro Dalcin         PetscDrawXiPixVal pix = XGetPixel(ximage,x,y);
101*f4e3882fSLisandro Dalcin         pixels[p++] = (unsigned char)PetscDrawXiPixelToColor(Xwin,pmap,pix);
102*f4e3882fSLisandro Dalcin       }
1038067a7d5SLisandro Dalcin     XDestroyImage(ximage);
1048067a7d5SLisandro Dalcin     *out_w      = w;
1058067a7d5SLisandro Dalcin     *out_h      = h;
1068067a7d5SLisandro Dalcin     *out_pixels = pixels;
1078067a7d5SLisandro Dalcin   }
1088067a7d5SLisandro Dalcin   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
1098067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
1108067a7d5SLisandro Dalcin }
111