X11:无法在使用 XCreateWindow 创建的透明 window 上绘制图像
X11 : Cannot draw an image on transparent window created with XCreateWindow
我正在尝试创建一个简单的 X11 window,它应该显示一个带有透明区域的 PNG 文件。我希望 window 本身没有(不透明)背景,以便 PNG 中的透明区域显示 window.
后面的内容
tl;dr 我无法将图像放在半透明 window;它给出 "Bad Match".
我可以使用 XCreateWindow 和 XMatchVisualInfo 成功创建半透明 window :
XSetWindowAttributes attr;
attr.colormap = XCreateColormap(display, DefaultRootWindow(display),
vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0x80800000; // Red, semi-transparent
Window window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,
width, height, 0, vinfo.depth, InputOutput, vinfo.visual,
CWColormap | CWBorderPixel | CWBackPixel, &attr);
(完整源代码如下)
然后我使用创建图像:
// "image32" is a generated image - see source code below
XImage *ximage = XCreateImage(display, visual, DefaultDepth(display,DefaultScreen(display)),
ZPixmap, 0, image32, width, height, 32, 0);
并在 Expose
事件期间显示图像:
XPutImage(display, window, DefaultGC(display, 0), ximage,
0, 0, 0, 0, width, height);
我用 gcc test.c -L/usr/X11R6/lib -lX11 -lXrandr -o test
编译,运行 用 ./test
编译:
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 72 (X_PutImage)
Serial number of failed request: 11
Current serial number in output stream: 12
注意: 如果我用这些替换创建 window (XCreateWindow) 的行:
Window window = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
width, height, 1, 0, 0);
正确显示window;但是,没有透明度。
我阅读了有关 XCreateWindow, XPutImage, XCreateImage 的文档并尝试使用多个参数,但没有成功。
我已阅读 this SO question 并尝试调整颜色深度;由于提到的文档 "Bad Match" 也可能因视觉效果不正确而被抛出,因此我检查过我的代码中的所有地方都发送了相同的视觉效果。
感谢任何帮助。
谢谢!
完整源代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
// Window size
int height = 256, width = 256;
XImage *CreateTrueColorImage(Display *display, Visual *visual)
{
int i, j;
unsigned char *image32=(unsigned char *)malloc(width*height*4);
unsigned char *p=image32;
for(i=0; i<width; i++)
{
for(j=0; j<height;j++)
{
*p++ = i;
*p++ = i;
*p++ = j;
*p++ = j; // alpha channel (should progressively get transparent towards left)
}
}
// Replacing "DefaultDepth(display,DefaultScreen(display))" with a hardcoded
// 24 or 32 still doesn't work with XCreateWindow. XCreateSimpleWindow works
// with hardcoded 24, but not 32.
return XCreateImage(display, visual, DefaultDepth(display,DefaultScreen(display)),
ZPixmap, 0, image32, width, height, 32, 0);
}
int main(int argc, char **argv)
{
XImage *ximage;
Display *display = XOpenDisplay(NULL);
Visual *visual = DefaultVisual(display, 0);
XVisualInfo vinfo;
XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, &vinfo);
XSetWindowAttributes attr;
attr.colormap = XCreateColormap(display, DefaultRootWindow(display),
vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0x80800000; // Red, semi-transparent
//Window window = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
// width, height, 1, 0, 0);
Window window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,
width, height, 0, vinfo.depth, InputOutput, vinfo.visual,
CWColormap | CWBorderPixel | CWBackPixel, &attr);
ximage = CreateTrueColorImage(display, vinfo.visual);
XSelectInput(display, window, ButtonPressMask|ExposureMask);
XMapWindow(display, window);
while(1)
{
XEvent event;
XNextEvent(display, &event);
switch(event.type)
{
case Expose:
XPutImage(display, window, DefaultGC(display, 0), ximage,
0, 0, 0, 0, width, height);
break;
case ButtonPress:
exit(0);
}
}
}
我通过进行两项更改设法让它工作。
首先,您应该为特定的 window.
创建一个 GC,而不是使用 DefaultGC(display, 0)
GC gc = XCreateGC(display, window, 0, 0);
因此,如果您将 XCreateImage
的深度硬编码为 32,它应该可以正常工作。
您也可以像这样使用 XVisualInfo
提供的深度
XCreateImage(display, vinfo.visual, vinfo.depth,
ZPixmap, 0, image32, width, height, 32, 0);
我正在尝试创建一个简单的 X11 window,它应该显示一个带有透明区域的 PNG 文件。我希望 window 本身没有(不透明)背景,以便 PNG 中的透明区域显示 window.
后面的内容tl;dr 我无法将图像放在半透明 window;它给出 "Bad Match".
我可以使用 XCreateWindow 和 XMatchVisualInfo 成功创建半透明 window :
XSetWindowAttributes attr;
attr.colormap = XCreateColormap(display, DefaultRootWindow(display),
vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0x80800000; // Red, semi-transparent
Window window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,
width, height, 0, vinfo.depth, InputOutput, vinfo.visual,
CWColormap | CWBorderPixel | CWBackPixel, &attr);
(完整源代码如下)
然后我使用创建图像:
// "image32" is a generated image - see source code below
XImage *ximage = XCreateImage(display, visual, DefaultDepth(display,DefaultScreen(display)),
ZPixmap, 0, image32, width, height, 32, 0);
并在 Expose
事件期间显示图像:
XPutImage(display, window, DefaultGC(display, 0), ximage,
0, 0, 0, 0, width, height);
我用 gcc test.c -L/usr/X11R6/lib -lX11 -lXrandr -o test
编译,运行 用 ./test
编译:
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 72 (X_PutImage)
Serial number of failed request: 11
Current serial number in output stream: 12
注意: 如果我用这些替换创建 window (XCreateWindow) 的行:
Window window = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
width, height, 1, 0, 0);
正确显示window;但是,没有透明度。
我阅读了有关 XCreateWindow, XPutImage, XCreateImage 的文档并尝试使用多个参数,但没有成功。
我已阅读 this SO question 并尝试调整颜色深度;由于提到的文档 "Bad Match" 也可能因视觉效果不正确而被抛出,因此我检查过我的代码中的所有地方都发送了相同的视觉效果。
感谢任何帮助。
谢谢!
完整源代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
// Window size
int height = 256, width = 256;
XImage *CreateTrueColorImage(Display *display, Visual *visual)
{
int i, j;
unsigned char *image32=(unsigned char *)malloc(width*height*4);
unsigned char *p=image32;
for(i=0; i<width; i++)
{
for(j=0; j<height;j++)
{
*p++ = i;
*p++ = i;
*p++ = j;
*p++ = j; // alpha channel (should progressively get transparent towards left)
}
}
// Replacing "DefaultDepth(display,DefaultScreen(display))" with a hardcoded
// 24 or 32 still doesn't work with XCreateWindow. XCreateSimpleWindow works
// with hardcoded 24, but not 32.
return XCreateImage(display, visual, DefaultDepth(display,DefaultScreen(display)),
ZPixmap, 0, image32, width, height, 32, 0);
}
int main(int argc, char **argv)
{
XImage *ximage;
Display *display = XOpenDisplay(NULL);
Visual *visual = DefaultVisual(display, 0);
XVisualInfo vinfo;
XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, &vinfo);
XSetWindowAttributes attr;
attr.colormap = XCreateColormap(display, DefaultRootWindow(display),
vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0x80800000; // Red, semi-transparent
//Window window = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
// width, height, 1, 0, 0);
Window window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,
width, height, 0, vinfo.depth, InputOutput, vinfo.visual,
CWColormap | CWBorderPixel | CWBackPixel, &attr);
ximage = CreateTrueColorImage(display, vinfo.visual);
XSelectInput(display, window, ButtonPressMask|ExposureMask);
XMapWindow(display, window);
while(1)
{
XEvent event;
XNextEvent(display, &event);
switch(event.type)
{
case Expose:
XPutImage(display, window, DefaultGC(display, 0), ximage,
0, 0, 0, 0, width, height);
break;
case ButtonPress:
exit(0);
}
}
}
我通过进行两项更改设法让它工作。 首先,您应该为特定的 window.
创建一个 GC,而不是使用DefaultGC(display, 0)
GC gc = XCreateGC(display, window, 0, 0);
因此,如果您将 XCreateImage
的深度硬编码为 32,它应该可以正常工作。
您也可以像这样使用 XVisualInfo
提供的深度
XCreateImage(display, vinfo.visual, vinfo.depth,
ZPixmap, 0, image32, width, height, 32, 0);