在Xlib中,从XImage中取出R,G,B三分量

使用Xlib开发X Window 程序的时候,图片一般都是用XImage这种数据格式保存的。

XImage的格式如下:

typedef struct _XImage {
	int width, height;		/* size of image */
	int xoffset;			/* number of pixels offset in X direction */
	int format;			/* XYBitmap, XYPixmap, ZPixmap */
	char *data;			/* pointer to image data */
	int byte_order;			/* data byte order, LSBFirst, MSBFirst */
	int bitmap_unit;		/* quant. of scanline 8, 16, 32 */
	int bitmap_bit_order;		/* LSBFirst, MSBFirst */
	int bitmap_pad;			/* 8, 16, 32 either XY or ZPixmap */
	int depth;			/* depth of image */
	int bytes_per_line;		/* accelerator to next scanline */
	int bits_per_pixel;		/* bits per pixel (ZPixmap) */
	unsigned long red_mask;		/* bits in z arrangement */
	unsigned long green_mask;
	unsigned long blue_mask;
	XPointer obdata;		/* hook for the object routines to hang on */
	struct funcs {			/* image manipulation routines */
		struct _XImage *(*create_image)();
		int (*destroy_image)();
		unsigned long (*get_pixel)();
		int (*put_pixel)();
		struct _XImage *(*sub_image)();
		int (*add_pixel)();
	} f;
} XImage;

最近,我写了个程序,需要从Linux中截去桌面,生成桌面的rgb数据,就是桌面的图片数据以rgb的形式保存,像素点从左到右,从上到下排列。每一个像素点由3bytes组成,分别是rgb,每个分量1byte。


大致的思路是:

1. 利用XLib API 获取到XImage数据

2. 从XImage中取出每一个像素点,大小为4bytes。再利用掩码(Color_mask)来取出每一个颜色分量。

3. 每一个分量保存在1byte的unsigned char中


PS: unsigned long 为4bytes 整数 (0 ~ 2^32-1),有时候程序里面有byte型,其实它是unsigned char的别名申明,从0 ~ 2^8 - 1 (255)

以下代码只是我程序中的一部分,不保证能运行成功。但是关键代码是对的,思路是这样的。


         #include  //用gcc编译的时候,需要在最后加上参数 -lX11
         Window desktop;
         Display* dsp; //每一个display可以有多个screen
         XImage* img;
         int screen_width;
         int screen_height;
 
         dsp = XOpenDisplay(NULL); //connect to X server
         if(dsp == NULL)
         {
                 printf("CaptureDesktop","Cannot connect to X server");
                 return 0;
         }
 
         desktop = RootWindow(dsp,0); //refer to root window
         if(desktop == 0)
         {
                 printf("CaptureDesktop","cannot get root window");
                 return 0;
         }
 
         /*Retrive the width and the height of the screen*/
         screen_width = DisplayWidth(dsp,0);
         screen_height = DisplayHeight(dsp,0);
 
         /*Get the Image of the root window */
         img = XGetImage(dsp,desktop,0,0,screen_width,screen_height,AllPlanes,ZPixmap); //XImage 中有三种保存格式,我这里用了ZPixmap,这种是一个pixel接着一个pixel保存的
          
 
	 
 unsigned long red_mask = img->red_mask; //这里的掩码也是4bytes,因为在XImage中ZPixmap中一个像素点也是4bytes,这里的掩码是用来萃取中对应的颜色
	 unsigned long green_mask = img->green_mask;
	 unsigned long blue_mask = img->blue_mask;
	 unsigned long pix;
	 uint8_t red, green, blue;

	 int nbits_mask = img->depth/3;
	 int t=0;
         unsigned char* data = (char*)malloc(sizeof(char)*screen_width*screen_height*3); //图片的长乘以宽乘以3就是图片数据的总大小
	 for(int i=0; iheight;i++)
	 {
	 	 for(int j=0;jwidth;j++)
	 	 {
			 pix = XGetPixel(img,j,i);//取出每一个像素点,从左到右,从上到下。
			 red = (pix & red_mask) >> (nbits_mask + nbits_mask); // 这里的红色的掩码值是00ff0000,做与操作后,向右走16位,取出八位,也就是1byte的红色值
		
		 	 *(data+t) = red;
			 t++;
			
			 green =(pix & green_mask) >> nbits_mask;// G绿色掩码值是0000ff00
			 *(data+t) = green;
			 t++;
			 blue = pix & blue_mask;//蓝色是000000ff
			 *(data+t) = blue;
			 t++;
		 }
	 }
    
      
 
 	 XDestroyImage(img);
	 XCloseDisplay(dsp);

	 return data;


你可能感兴趣的:(C++编程,Linux相关)