如何将32位图像上传到服务器端像素图

我正在尝试从客户端缓冲区创建服务器端RGBA像素图。 CreatePixmap和CreateImage适用于32位和24位,但XPutImage会导致服务器返回匹配错误

X Error of failed request: BadMatch (invalid parameter attributes) Major opcode of failed request: 72 (X_PutImage) Serial number of failed request: 8 Current serial number in output stream: 8 

服务器支持32位pixmaps(xdpyinfo输出: https ://gist.github.com/2582961)。 在ubuntu 12.04(X.Org版本:1.11.3)和OSX与X.app(X.Org版本:1.10.3)上的行为相同

为什么以下代码失败?

 #include  #include  int main(int argc, char **argv) { int width = 100; int height = 100; int depth = 32; // works fine with depth = 24 int bitmap_pad = 32; // 32 for 24 and 32 bpp, 16, for 15&16 int bytes_per_line = 0; // number of bytes in the client image between the start of one scanline and the start of the next Display *display=XOpenDisplay(0); unsigned char *image32=(unsigned char *)malloc(width*height*4); XImage *img = XCreateImage(display, CopyFromParent, depth, ZPixmap, 0, image32, width, height, bitmap_pad, bytes_per_line); Pixmap p = XCreatePixmap(display, XDefaultRootWindow(display), width, height, depth); XPutImage(display, p, DefaultGC(display, 0), img, 0, 0, 0, 0, width, height); // 0, 0, 0, 0 are src x,y and dst x,y XEvent ev; while (1) { XNextEvent(display, &ev); } } 

更新:看起来我终于得到了答案:使用与pixmap相关联的GC而不是DefaultGC(具有根窗口的深度)

 #include  #include  int main(int argc, char **argv) { int width = 100; int height = 100; int depth = 32; // works fine with depth = 24 int bitmap_pad = 32; // 32 for 24 and 32 bpp, 16, for 15&16 int bytes_per_line = 0; // number of bytes in the client image between the start of one scanline and the start of the next Display *display=XOpenDisplay(0); unsigned char *image32=(unsigned char *)malloc(width*height*4); XImage *img = XCreateImage(display, CopyFromParent, depth, ZPixmap, 0, image32, width, height, bitmap_pad, bytes_per_line); Pixmap p = XCreatePixmap(display, XDefaultRootWindow(display), width, height, depth); XGCValues gcvalues; GC gc = XCreateGC(display, p, 0, &gcvalues); XPutImage(display, p, gc, img, 0, 0, 0, 0, width, height); // 0, 0, 0, 0 are src x,y and dst x,y XEvent ev; while (1) { XNextEvent(display, &ev); } } 

好吧,如果你只是创建一个通过一个32位参数的绘图的GC,你的代码适用于32位图像。 XCreateGC(dpy,drawable,0,0),其中drawable可以是32位深度的像素图。 它与我完美搭配。

问题在于DefaultGC()返回具有系统默认屏幕位深度的GC。 如果你看一下gist paste的第53行,你会看到这是24:

根窗深度:24架飞机

在第63行,您会看到它默认使用0x22,在第64行到第70行中有更详细的显示:

  visual: visual id: 0x22 class: TrueColor depth: 24 planes available colormap entries: 256 per subfield red, green, blue masks: 0xff0000, 0xff00, 0xff significant bits in color specification: 8 bits 

你可以做得更好一些,但作为一个开始,你可以试试这个:

注意:这使用系统视觉效果,因此最有可能仅支持24或32的深度。

 #include  #include  #include  #include  #ifdef DEBUG int dbg = 1; #else int dbg = 0; #endif /* Return a GC based on depth */ int gc_depth(int depth, Display *dpy, Window scr, Window root, GC *gc) { Window win; Visual *visual; XVisualInfo vis_info; XSetWindowAttributes win_attr; unsigned long win_mask; if(!XMatchVisualInfo(dpy, scr, depth, TrueColor, &vis_info)) { fprintf(stderr, " * ERR: %d depth not supported\n", depth ); return 1; } visual = vis_info.visual; win_attr.colormap = XCreateColormap(dpy, root, visual, AllocNone); win_attr.background_pixel = 0; win_attr.border_pixel = 0; win_mask = CWBackPixel | CWColormap | CWBorderPixel; win = XCreateWindow( dpy, root, 0, 0, 100, 100, /* dummy size */ 0, depth, InputOutput, visual, win_mask, &win_attr); /* To flush out any errors */ if (dbg) XSync(dpy, True); *gc = XCreateGC(dpy, win, 0, 0); if (dbg) XSync(dpy, True); XDestroyWindow(dpy, win); if (dbg) XSync(dpy, True); return 0; } int main(void) { int w = 100; int h = 100; int depth = 32; int bitmap_pad = 32; int bpl = 0; Display *dpy; Window root; Window scr; GC gc; int root_depth; Pixmap pm; XImage *img; unsigned char *buf_img; if(!(dpy = XOpenDisplay(NULL))) { fprintf(stderr, " * ERR: Failed to open display.\n"); return 1; } #ifdef DEBUG /* To get errors in order, slows down * One can also define int _Xdebug = 1; * */ XSynchronize(dpy, True); #endif root = XDefaultRootWindow(dpy); scr = XDefaultScreen(dpy); if ((buf_img = malloc(w * h * 4)) == NULL) { fprintf(stderr, " * ERR: Unable to alloacte %d bytes\n", w * h * 4); return 1; } root_depth = DefaultDepth(dpy, scr); fprintf(stderr, "Default depth: %d\n", root_depth); /* This should be doen more nice */ if (depth != root_depth) { if (gc_depth(depth, dpy, scr, root, &gc) != 0) return 1; } else { gc = DefaultGC(dpy, 0); } img = XCreateImage( dpy, CopyFromParent, depth, ZPixmap, 0, (char *)buf_img, w, h, bitmap_pad, bpl); /* To flush out any errors */ if (dbg) XSync(dpy, True); pm = XCreatePixmap( dpy, root, w, h, depth); if (dbg) XSync(dpy, True); XPutImage( dpy, pm, gc, img, 0, 0, 0, 0, w, h); if (dbg) XSync(dpy, True); XFreePixmap(dpy, pm); XDestroyImage(img); XFreeGC(dpy, gc); if (dbg) XSync(dpy, True); fprintf(stderr, "OK!\n"); return 0; }