Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I render an image using python-xlib?

I am trying to make a window manager in python 3 and I need to find out how to render 16x16 window icons.

I have used Pillow and Xlib to render a dummy image, and I was expecting that it would work, but nope! It didn't.

The test program is mostly just initializing the window and generating the image, the faulty part is (at least one problem, there probably are more): screen.default_visual. I can't find any documentation on ANY of this, any help would be appreciated.

from Xlib import display, X, Xutil
from PIL import Image, ImageDraw
import os

def renderPng(image_path, width, height, x=50, y=50):
    img = Image.open(image_path)
    if img.mode != 'RGB':
        img = img.convert('RGB')
    image_data = img.tobytes("raw", "RGB")
    disp = display.Display()
    screen = disp.screen()
    root = screen.root
    visual = screen.root_visual
    depth = screen.root_depth
    win = root.create_window(
        x, y,
        width, height,
        1,
        depth,
        X.InputOutput,
        visual,
        background_pixel=screen.white_pixel,
        event_mask=X.ExposureMask | X.KeyPressMask | X.StructureNotifyMask
    )
    win.set_wm_name("PNG image")
    win.map()
    gc = win.create_gc(
        foreground=screen.black_pixel,
        background=screen.white_pixel
    )
    ximage = X.Image(
        data=image_data,
        width=16,
        height=16,
        depth=depth,
        bitmap_unit=8,
        bitmap_pad=32,
        byte_order=X.LSBFirst,
        bitmap_bit_order=X.LSBFirst,
        format=X.ZPixmap,
        bytes_per_line=16 * 3
    )
    while True:
        event = disp.next_event()
        if event.type == X.Expose:
            if event.count == 0:
                win.put_image(gc, ximage, 0, 0, 0, 0, 16, 16)
                disp.flush()
        elif event.type == X.KeyPress:
            break
        elif event.type == X.ConfigureNotify:
            pass
    win.destroy()
    disp.close()

if __name__ == '__main__':
    dummy = "dummy.png"
    if not os.path.exists(dummy):
        img = Image.new('RGB', (16, 16), color = 'red')
        d = ImageDraw.Draw(img)
        d.text((1,1), "abc", fill=(255,255,255))
        img.save(dummy)
    renderPng(dummy, 200, 200, 100, 100)

And the code gives me this error:

Traceback (most recent call last):
  File "/home/spincube/x/test.py", line 63, in <module>
    renderPng(dummy, 200, 200, 100, 100)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/spincube/x/test.py", line 31, in renderPng
    ximage = X.Image(
             ^^^^^^^
AttributeError: module 'Xlib.X' has no attribute 'Image'

UPDATE: I changed default_visual to root_visual.

like image 340
SpinningCubes Avatar asked Dec 06 '25 03:12

SpinningCubes


1 Answers

I couldn't find default_visual but there is root_visual

I couldn't find X.Image but there is put_pil_image() which can put directly PIL.Image without converting to bytes and without X.Image

from Xlib import display, X  #, Xutil
from PIL import Image, ImageDraw
import os

def render_png(image_path, width, height, x=50, y=50):

    img = Image.open(image_path)
    if img.mode != 'RGB':
        img = img.convert('RGB')
    #image_data = img.tobytes("raw", "RGB")

    disp = display.Display()
    screen = disp.screen()
    root = screen.root

    visual = screen.root_visual  # no exists `default_visual`
    depth = screen.root_depth

    win = root.create_window(
        x, y,
        width, height,
        1,
        depth,
        X.InputOutput,
        visual,
        background_pixel=screen.white_pixel,
        event_mask=X.ExposureMask | X.KeyPressMask | X.StructureNotifyMask
    )

    win.set_wm_name("PNG image")
    win.map()

    gc = win.create_gc(
        foreground=screen.black_pixel,
        background=screen.white_pixel
    )

    while True:
        event = disp.next_event()
        if event.type == X.Expose:
            if event.count == 0:
                win.put_pil_image(gc, 0, 0, img)
                disp.flush()
        elif event.type == X.KeyPress:
            break
        elif event.type == X.ConfigureNotify:
            pass

    win.destroy()
    disp.close()

if __name__ == '__main__':
    dummy = "dummy.png"

    if not os.path.exists(dummy):
        img = Image.new('RGB', (16, 16), color = 'red')
        d = ImageDraw.Draw(img)
        d.text((1,1), "abc", fill=(255,255,255))
        img.save(dummy)

    render_png(dummy, 200, 200, 100, 100)

enter image description here

like image 95
furas Avatar answered Dec 08 '25 18:12

furas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!