André Wagner
André Wagner

Reputation: 1477

Draw an image with transparent color in X11 using XCB

I'm using xcb library for X11. I loaded an image with a transparent color from a PNG into a pixmap, and I'm trying to draw it in a window. However, the transparent color is not transparent when I draw it using xcb_copy_area.

I was thinking that a possible way to do that is to create a mask from the image, and then apply the image with the mask. But I don't know how to do that, and documentation on this is very sparse.

I wonder if someone can provide me with an example or an explanation on how to do that.

EDIT: I was asked to add a photo of the issue, and the code I'm using. Here it goes:

    // load PNG
    int w, h;
    int comp;
    uint8_t* data = stbi_load_from_memory((stbi_uc const *) df.data.data(), (int) df.data.length(),
                                          &w, &h, &comp, 4);

    // organize pixels
    unsigned* dp = (unsigned*) data;
    for(size_t i = 0, len = w * h; i < len; i++) {
        dp[i] = dp[i] & 0xff00ff00 | ((dp[i] >> 16) & 0xFF) | ((dp[i] << 16) & 0xFF0000);
    }

    // create image
    xcb_gcontext_t gc = xcb_generate_id(dpy_);
    xcb_pixmap_t px = xcb_generate_id(dpy_);
    xcb_create_pixmap(dpy_, scr_->root_depth, px, scr_->root, w, h);
    xcb_create_gc(dpy_, gc, px, 0, nullptr);
    xcb_image_t* image = xcb_image_create_native(dpy_, w, h, XCB_IMAGE_FORMAT_Z_PIXMAP, scr_->root_depth, (uint8_t *) dp, w * h * 4, (uint8_t *) dp);
    xcb_image_put(dpy_, px, gc, image, 0, 0, 0);
    xcb_image_destroy(image);
    xcb_free_gc(dpy_, gc);

    // paste pixmap
    xcb_copy_area(dpy_, px, id, gc_, 0, 0, 50, 50, w, h);
    xcb_flush(dpy_);

And this is the image, what I would expect to happen, and what is happening:

enter image description here

Upvotes: 0

Views: 356

Answers (1)

Uli Schlachter
Uli Schlachter

Reputation: 9877

Half an answer that I am still posting as an answer (if someone wants to, they can add a working example to this, but the question already does not have a working example):

Core X11 can only do binary transparency, i.e. 0% and 100% opacity.

Anything more requires the Render extension. Random Google result for its documentation is https://www.x.org/releases/X11R7.5/doc/renderproto/renderproto.txt. Its Composite request can draw something that involves transparency.

To actually use this, you need to find a "picture format" you want to use. I would recommend searching for one of the "Standard PictFormats" from section 7 of the doc. The ARGB8 format is likely a good choice. You then create a pixmap with the correct depth (32 in the ARGB8 example), upload your image to it, create pictures for the pixmap and the target window and can finally use xcb_render_composite to draw the pixmap to the target window.

Upvotes: 1

Related Questions