2016-09-15 18 views
1

私は、Xlibフォームでのアルファチャンネル処理を実証するstackoverflowとGitHubからコピーされた2つのソースコードを持っています。最初は単純なXlib、次にOpenGLです。しかし、私は誤って作業しています。Linux Xlibの誤ったアルファハンドリング

アルファチャンネルの値を0に設定すると、黒だけでなく透明になるはずですが、色が白に近いほどアルファチャンネルが少なくなります。色を白に設定すると、ウィンドウはアルファチャンネルを完全に無視しています。 0x00808080は半透明です。

私は何が間違っているのか分かりませんが、問題が何であるか教えていただけますか?マシンに問題があるのでしょうか?ここで

は、最初のコードスニペットです:

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

int main(int argc, char* argv[]) 
{ 
    Display* display = XOpenDisplay(NULL); 

    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 = 0x00ffffff; 

    Window win = XCreateWindow(display, DefaultRootWindow(display), 0, 0, 300, 200, 0, vinfo.depth, InputOutput, vinfo.visual, CWColormap | CWBorderPixel | CWBackPixel, &attr); 
    XSelectInput(display, win, StructureNotifyMask); 
    GC gc = XCreateGC(display, win, 0, 0); 

    Atom wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", 0); 
    XSetWMProtocols(display, win, &wm_delete_window, 1); 

    XMapWindow(display, win); 

    int keep_running = 1; 
    XEvent event; 

    while (keep_running) { 
     XNextEvent(display, &event); 

     switch(event.type) { 
      case ClientMessage: 
       if (event.xclient.message_type == XInternAtom(display, "WM_PROTOCOLS", 1) && (Atom)event.xclient.data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", 1)) 
        keep_running = 0; 

       break; 

      default: 
       break; 
     } 
    } 

    XDestroyWindow(display, win); 
    XCloseDisplay(display); 
    return 0; 
} 

そして、ここでは、第二次のとおりです。

/* 
     ____  _____ 
    /\__ \ /\ ___\ 
    \/__/\ \ \ \ \__/_ 
     \ \ \ \ \____ \ 
     _\_\ \ \/__/_\ \ 
     /\ _____\ /\ _____\ 
     \/______/ \/______/ 

    Copyright (C) 2011 Joerg Seebohn 

    This program is free software; you can redistribute it and/or modify 
    it under the terms of the GNU General Public License as published by 
    the Free Software Foundation; either version 2 of the License, or 
    (at your option) any later version. 

    This program demonstrates how an X11 window with OpenGL support 
    can be drawn transparent. 

    The title bar and window border drawn by the window manager are 
    drawn opaque. 
    Only the background of the window which is drawn with OpenGL 
     glClearColor(0.7, 0.7, 0.7, 0.7) ; 
     glClear(GL_COLOR_BUFFER_BIT) ; 
    is 30% transparent. 

    Compile it with: 
    gcc -std=gnu99 -o test testprogram.c -lX11 -lGL 
*/ 
#include <X11/Xlib.h> 
#include <X11/Xatom.h> 
#include <X11/keysym.h> 

#include <GL/gl.h> 
#include <GL/glx.h> 

#include <stdio.h> 
#include <stdlib.h> 



int main(int argc, char* argv[]) 
{ 
    Display * display = XOpenDisplay(0) ; 
    const char * xserver = getenv("DISPLAY") ; 

    if (display == 0) 
    { 
     printf("Could not establish a connection to X-server '%s'\n", xserver) ; 
     exit(1) ; 
    } 

    // query Visual for "TrueColor" and 32 bits depth (RGBA) 
    XVisualInfo visualinfo ; 
    XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, &visualinfo); 

    // create window 
    Window win ; 
    GC  gc ; 
    XSetWindowAttributes attr ; 
    attr.colormap = XCreateColormap(display, DefaultRootWindow(display), visualinfo.visual, AllocNone) ; 
    attr.event_mask = ExposureMask | KeyPressMask ; 
    attr.background_pixmap = None ; 
    attr.border_pixel  = 0 ; 
    win = XCreateWindow( display, DefaultRootWindow(display), 
          50, 300, 400, 100, // x,y,width,height : are possibly opverwriteen by window manager 
          0, 
          visualinfo.depth, 
          InputOutput, 
          visualinfo.visual, 
          CWColormap|CWEventMask|CWBackPixmap|CWBorderPixel, 
          &attr 
          ) ; 
    gc = XCreateGC(display, win, 0, 0) ; 

    // set title bar name of window 
    XStoreName(display, win, "Transparent Window with OpenGL Support") ; 

    // say window manager which position we would prefer 
    XSizeHints sizehints ; 
    sizehints.flags = PPosition | PSize ; 
    sizehints.x  = 50 ; sizehints.y = 300 ; 
    sizehints.width = 400 ; sizehints.height = 100 ; 
    XSetWMNormalHints(display, win, &sizehints) ; 
    // Switch On >> If user pressed close key let window manager only send notification >> 
    Atom wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", 0) ; 
    XSetWMProtocols(display, win, &wm_delete_window, 1) ; 

    { 
     // change foreground color to brown 
     XColor xcol ; 
     xcol.red = 153 * 256 ; // X11 uses 16 bit colors ! 
     xcol.green = 116 * 256 ; 
     xcol.blue = 65 * 256 ; 
     XAllocColor(display, attr.colormap, &xcol) ; 
     XGCValues gcvalues ; 
     gcvalues.foreground = xcol.pixel ; 
     XChangeGC(display, gc, GCForeground, &gcvalues) ; 
    } 

    // create OpenGL context 
    GLXContext glcontext = glXCreateContext(display, &visualinfo, 0, True) ; 
    if (!glcontext) 
    { 
     printf("X11 server '%s' does not support OpenGL\n", xserver) ; 
     exit(1) ; 
    } 
    glXMakeCurrent(display, win, glcontext) ; 

    // now let the window appear to the user 
    XMapWindow(display, win) ; 

    int isUserWantsWindowToClose = 0 ; 

    while(!isUserWantsWindowToClose) 
    { 
     int isRedraw = 0 ; 

     /* XPending returns number of already queued events. 
     * If no events are queued XPending sends all queued requests to the X-server 
     * and tries to read new incoming events. */ 

     while(XPending(display) > 0) 
     { 
     // process event 
     XEvent event ; 
     XNextEvent(display, &event) ; 

     switch(event.type) 
     { // see 'man XAnyEvent' for a list of available events 
     case ClientMessage: 
        // check if the client message was send by window manager to indicate user wants to close the window 
        if ( event.xclient.message_type == XInternAtom(display, "WM_PROTOCOLS", 1) 
         && event.xclient.data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", 1) 
         ) 
        { 
        isUserWantsWindowToClose = 1 ; 
        } 
        break; 
     case KeyPress: 
        if (XLookupKeysym(&event.xkey, 0) == XK_Escape) 
        { 
        isUserWantsWindowToClose = 1 ; 
        } 
        break ; 
     case Expose: 
        isRedraw = 1 ; 
        break ; 
     default: 
       // do nothing 
       break ; 
     } 

     } 

     // ... all events processed, now do other stuff ... 

     if (isRedraw) 
     { // needs redraw 
     // use opengl to clear background in (transparent) light grey 
     glClearColor(1, 1, 1, 0) ; 
     glClear(GL_COLOR_BUFFER_BIT) ; 
     glXSwapBuffers(display, win) ; 
     glXWaitGL() ; 
     // draw string with X11 
     XDrawString(display, win, gc, 10, 20, "Hello ! ", 7) ; 
     } 

     // ... do something else ... 

    } 

    XDestroyWindow(display, win) ; 
    win = 0 ; 
    XCloseDisplay(display) ; 
    display = 0 ; 

    return 0 ; 
} 
+0

再描画について:openglで白(透明)にして、前後を反転してから、xlibを使ってその上に茶色の文字列を描画します。私が正しいとすれば、既に描かれたサーフェス(アルファに関係なく白です)と文字列をブレンドすることはありません。これを行うには、XRenderライブラリが提供する機能を使用してブレンド操作を指定する必要があります。 – Andreas

+0

いいえ、あなたは誤解しました。文字列ではなく背景色です。 背景色のアルファチャンネルをゼロに設定した場合、他のチャンネルが何を含んでいても、背景は完全に透明でなければなりません。 しかし、他のチャンネルを黒以外に設定すると、背景が完全に透明ではありません。 (色が明るいほど、背景が透明になりません) – jsr

+0

Ok。あなたは背景の背後に何を持っていたいですか? – Andreas

答えて

1

別のトピックでは問題が解決されました: How to create semi transparent white window in XLib 答えは色を事前に乗じましたアルファチャンネル。

+0

これはほぼ確実です。あらかじめ乗算されたアルファを渡すと、多くのルーチンがより効率的に動作するため、APIが要求することがあります。 –