Skip to content

SLM Display

slmdisplay

My_SLM

My_SLM(screen_index: int = 0)

Fullscreen numpy-array display on a chosen physical monitor. Uses plain tkinter (stdlib) - the image is shown as ordinary CPU-composited window content.

Source code in structured_optics\slmdisplay.py
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
def __init__(self, screen_index: int = 0):
    monitors = get_monitors()
    if screen_index >= len(monitors):
        raise ValueError("Invalid screen index")

    m = monitors[screen_index]
    self.width, self.height = m.width, m.height

    self.root = tk.Tk()
    self.root.overrideredirect(True)  # borderless
    self.root.geometry(f"{self.width}x{self.height}+{m.x}+{m.y}")
    self.root.attributes("-topmost", True)
    self.root.configure(bg="black")

    self.label = tk.Label(self.root, bd=0, highlightthickness=0, bg="black")
    self.label.pack(fill="both", expand=True)

    self.root.update_idletasks()
    self.root.update()

    self._photo_ref = None  # keep the PhotoImage alive (Tk drops it otherwise)
    self._img_ref = None

update_image

update_image(img: ndarray)

img: - (H, W) uint8 -> grayscale - (H, W, 3) uint8 -> RGB

Source code in structured_optics\slmdisplay.py
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
def update_image(self, img: np.ndarray):
    """
    img:
      - (H, W) uint8      -> grayscale
      - (H, W, 3) uint8   -> RGB
    """
    if img.dtype != np.uint8:
        raise TypeError("Image must be uint8")

    img = np.ascontiguousarray(img)
    self._img_ref = img  # keep a reference alive

    if img.ndim == 2:
        h, w = img.shape
        header = f"P5\n{w} {h}\n255\n".encode()
    elif img.ndim == 3 and img.shape[2] == 3:
        h, w, _ = img.shape
        header = f"P6\n{w} {h}\n255\n".encode()
    else:
        raise ValueError("Image must be (H,W) or (H,W,3)")

    # Build a raw PGM/PPM blob in memory - Tk's built-in photo image
    # reader parses this directly in C, so no PIL/Pillow dependency
    # and no per-pixel Python loop.
    data = header + img.tobytes()
    photo = tk.PhotoImage(data=data)

    self._photo_ref = photo
    self.label.configure(image=photo)

    self.root.update()