【问题标题】:How to upload 32 bit image to server-side pixmap如何将 32 位图像上传到服务器端像素图
【发布时间】:2012-05-16 13:30:10
【问题描述】:

我正在尝试从客户端缓冲区创建服务器端 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 位像素图(xdpyinfo 输出:https://gist.github.com/2582961)。在 ubuntu 12.04(X.Org 版本:1.11.3)和带有 X.app(X.Org 版本:1.10.3)的 OSX 上的行为相同

为什么下面的代码会失败?

#include     <stdlib.h>
#include     <X11/Xlib.h>

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     <stdlib.h>
#include     <X11/Xlib.h>

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

【问题讨论】:

    标签: c x11 xlib


    【解决方案1】:

    问题在于DefaultGC(),它返回一个具有系统默认屏幕位深度的 GC。如果您查看要点粘贴的第 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 <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;
    }
    

    【讨论】:

    • 谢谢!不幸的是,您的方法需要 32 位视觉(和虚拟 32 位深度窗口),这在 OSX 上不可用(请参阅我的 dpyinfo)。
    • @AndreySidorov:是的,我正要发布它,因为我更仔细地阅读了您的要点。真可惜。那就得搞点别的了。无论如何:至少问题更具体。
    • 据我所知,GC 并不特定于深度(所有可能的 GC 属性都不是指深度)。来自x11协议的PutImage请求说明:GC组件:function、plane-mask、subwindow-mode、clip-x-origin、clip-y-origin、clip-mask; GC模式相关组件:前台、后台
    • 我可能会尝试使用两个 24 位 PutImage 请求,两个 24 位像素图 + 一个 32 位,并使用 CopyArea 和平面掩码将它们组合起来,但我真的希望有更简单的解决方案
    • 太糟糕了。仍然破解了一段时间,但没有找到可用的解决方案。
    【解决方案2】:

    好吧,如果您只是创建一个 GC 并传递一个 32 位的可绘制参数,那么您的代码适用于 32 位图像。 XCreateGC(dpy, drawable, 0, 0),其中drawable可以是32位深度的像素图。它非常适合我。

    【讨论】:

    • 现在我有鸡和蛋的问题 - 我需要 32 位 gc 来创建 32 位像素图和 32 位可绘制来创建 32 位 gc。你有默认视觉的 32 位深度吗?
    • 下周我回去工作时会回复你的,因为我现在正在休假。我去找找好吗?
    • 谢谢!这绝不是紧急的
    • 上次我完全忘记了这一点。但是你的意思是你需要 32 位 GC 来创建 32 位像素图? XCreatePixmap(display, d, width, height, depth);您只需向像素图指定创建时所需的深度。您为什么遇到问题?
    • 原代码中的问题是 XPutImage 调用未能上传 32 位位图。我将使用工作代码更新答案。使用为像素图创建的 GC 而不是 DefaultGC(display, 0) 成功了
    猜你喜欢
    • 1970-01-01
    • 2015-06-29
    • 2022-09-26
    • 2020-05-06
    • 1970-01-01
    • 1970-01-01
    • 2017-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多