所以,我正在尝试使用XImage,创建了我的第一个屏幕捕获程序,它工作正常。现在我想通过thrift将这个XImage发送到另一台机器并将其保存在那里,但由于客户端存在一些数据读取问题,因此我将整个服务器端代码转移到客户端(用于测试目的。我最终将移动它回到服务器端)
代码:
transport->open();
Display *display = XOpenDisplay(NULL);
Window root = DefaultRootWindow(display);
XWindowAttributes gwa;
XGetWindowAttributes(display, root, &gwa);
int width = gwa.width;
int height = gwa.height;
XImage *image = XGetImage(display,root, 0,0 , width,height,AllPlanes, ZPixmap);
char *data = image->data;
int imgwidth = image->width;
int imgheight = image->height;
int depth = image->depth;
int offset = 0;
int xpad = 32; //may be 8 or 16 or 32
int format = ZPixmap;
int bytes_per_line = image->bytes_per_line;
sendImage image_send;
ostringstream s;
//s<<image->data;
s.write(image->data,(width)*(height));
image_send.width = imgwidth;
image_send.height = imgheight;
image_send.depth = depth;
image_send.offset = 2000;
image_send.data = s.str();
image_send.xpad = xpad;
image_send.format = format;
image_send.bytes_per_line = bytes_per_line;
//server side code
int width1 = image_send.width;
int height1 = image_send.height;
int depth1 = image_send.depth;
int offset1 = image_send.offset;
char* tmp = new char[image_send.data.length() + 1];
strcpy(tmp,image_send.data.c_str());
char *data1 = tmp;
int xpad1 = image_send.xpad;
int format1 = image_send.format;
int bytes_per_line1 = image_send.bytes_per_line;
//Initialising X Operations
//Display *display = XOpenDisplay(NULL);
//Window root = DefaultRootWindow(display);
//XWindowAttributes gwa;
//XGetWindowAttributes(display, root, &gwa);
int serverwidth = gwa.width;
int serverheight = gwa.height;
XImage *image1 = XCreateImage(display,DefaultVisual(display,DefaultScreen(display)),depth1, format1,offset1,data1,width1,height1,xpad1, bytes_per_line1);
unsigned char *array = new unsigned char[width * height * 3];
unsigned long red_mask = image1->red_mask;
unsigned long green_mask = image1->green_mask;
unsigned long blue_mask = image1->blue_mask;
CImg<unsigned char> pic(array,width,height,1,3);
for (int x = 0; x < width1; x++)
for (int y = 0; y < height1 ; y++)
{
unsigned long pixel = XGetPixel(image1,x,y);
unsigned char blue = pixel & blue_mask;
unsigned char green = (pixel & green_mask) >> 8;
unsigned char red = (pixel & red_mask) >> 16;
array[(x + width1 * y) * 3] = red;
array[(x + width1* y) * 3+1] = green;
array[(x + width1 * y) * 3+2] = blue;
pic(x,y,0,0) = red;
pic(x,y,0,1) = green;
pic(x,y,0,2) = blue;
}
pic.save_png("blah1.png");
正如你所看到我从图像指针中取出数据部分,将其写入流然后将该值分配给thrift对象(image_send)
对于服务器端。我使用c_str()将其存储到data1中,然后使用data1
使用XCreateImage如果我将data1作为XCreateImage
中的源传递,这是我得到的输出
这是我得到的输出,如果我使用数据(来自原始XImage的客户端变量)
我们可以看到第一张图片中有很多空白。在进一步检查时,我发现data1在开始时包含大量null,而数据不是
所以,我相信数据在从char *转换为字符串流然后再转换为char *时会被破坏。
你会给出什么建议来纠正这个问题? 更新:
所以,我正在尝试各种各样的东西,它终于奏效了。问题结果是缓冲区分配和使用strcpy(我猜)我改为memcpy
int main() {
Display *display = XOpenDisplay(NULL);
Window root = DefaultRootWindow(display);
XWindowAttributes gwa;
XGetWindowAttributes(display, root, &gwa);
int width = gwa.width;
int height = gwa.height;
XImage *image = XGetImage(display,root, 0,0 , width,height,AllPlanes, ZPixmap);
char *data = image->data;
int imgwidth = image->width;
int imgheight = image->height;
int depth = image->depth;
int offset = 0;
int xpad = 32; //may be 8 or 16 or 32
int format = ZPixmap;
int bytes_per_line = image->bytes_per_line;
//sendImage image_send;
ostringstream s;
//s<<image->data;
s.write(data,(width)*(height) * 4);
string stemp = s.str();
//server side code
int width1 = width;
int height1 = height;
int depth1 = depth;
int offset1 = offset;
char* tmp = new char[stemp.length()];
//strcpy(tmp,stemp.c_str());
memcpy(tmp,stemp.data(),stemp.length());
char *data1 = tmp;
int xpad1 = 32;
int format1 = ZPixmap;
int bytes_per_line1 = bytes_per_line;
int serverwidth = gwa.width;
int serverheight = gwa.height;
XImage *image1 = XCreateImage(display,DefaultVisual(display,DefaultScreen(display)),depth1, format1,offset1,data1,serverwidth,serverheight,xpad1, bytes_per_line1);
unsigned char *array = new unsigned char[width * height];
unsigned long red_mask = image1->red_mask;
unsigned long green_mask = image1->green_mask;
unsigned long blue_mask = image1->blue_mask;
CImg<unsigned char> pic(array,width,height,1,3);
for (int x = 0; x < width1; x++) {
for (int y = 0; y < height1 ; y++)
{
unsigned long pixel = XGetPixel(image1,x,y);
unsigned char blue = pixel & blue_mask;
unsigned char green = (pixel & green_mask) >> 8;
unsigned char red = (pixel & red_mask) >> 16;
pic(x,y,0,0) = red;
pic(x,y,0,1) = green;
pic(x,y,0,2) = blue;
}
}
pic.save_png("blah.png");
return 0;
}
然而,有些事情我不明白
1)当我写数据流时为什么我必须将缓冲区的大小设为(width * height * 4)。任何不足都会按比例裁剪图像。如果我理解正确,缓冲区大小不应该等于屏幕的宽度*高度,还是结构更像红色,绿色,蓝色和深度?
2)我的缓冲区大小约为4MB,但图像大小约为150K,是否由于编码
3)是否会持续分配和释放这么大的缓冲区大小,阻碍性能?
修改:为了将来的目的
第一个问题的答案是:我们可以使用(bytes_per_line height)得到相同的结果,它偶然给出了与width height * 4相同的结果
答案 0 :(得分:0)
图像数据是二进制的,你不能把它当作C字符串来操纵它。第一个零字节会破坏聚会。
使用std::string::data()
和/或memcpy
,而不是std::string::str()
或strcpy
。
我不知道这是否是唯一的问题。 (width)*(height)
看起来很可疑。你有一个字节的像素吗?