How to upload 32 bit image to server-side pixmap

匿名 (未验证) 提交于 2019-12-03 01:59:02

问题:

I'm trying to create server-side RGBA pixmap from client-side buffer. CreatePixmap & CreateImage work ok for 32 and 24 bit, but XPutImage result in Match Error returned by server

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

server does support 32 bit pixmaps (xdpyinfo output: https://gist.github.com/2582961). Same behaviour on ubuntu 12.04 (X.Org version: 1.11.3) and OSX with X.app (X.Org version: 1.10.3)

Why following code fails?

#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);     } }

Update: It looks like I finally got answer: use GC associated with pixmap instead of DefaultGC (which has depth of root window)

#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);     } }

回答1:

Well, your code works for 32 bits images if you just create a GC passing a drawable on argument which is 32 bits. XCreateGC(dpy, drawable, 0, 0), where drawable can be a pixmap with 32 bits depth. It works perfect with me.



回答2:

The problem is with DefaultGC() which return a GC with bit depth of system default screen. If you look at line 53 of your gist paste you see that this is 24:

depth of root window: 24 planes

On line 63 you see that it uses 0x22 as default which is shown in more detail in line 64 to 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

You could probably do this a bit nicer but as a start you can try this:

Note: This uses system visuals so most probably only support depth of 24 or 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; }


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!