How to upload 32 bit image to server-side pixmap

后端 未结 2 1197
误落风尘
误落风尘 2020-12-15 07:39

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

相关标签:
2条回答
  • 2020-12-15 08:12

    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 <stdio.h>
    #include <stdlib.h>
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    
    
    #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;
    }
    
    0 讨论(0)
  • 2020-12-15 08:24

    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.

    0 讨论(0)
提交回复
热议问题