Note
Go to the end to download the full example code.
ImGui cmap picker
Imgui example that shows how to create a colormap picker menu
Uses the cmap library: https://github.com/tlambert03/cmap
pip install cmap
Instead of using the cmap library you can create 2D arrays in the shape [2, 255, 3] that represent the LUT for the colormap
# run_example = false
import numpy as np
import wgpu
from imgui_bundle import imgui
from rendercanvas.auto import RenderCanvas, loop
from wgpu.utils.imgui import ImguiRenderer
from cmap import Colormap
# Create a canvas to render to
canvas = RenderCanvas(
title="imgui", size=(512, 256), max_fps=60, update_mode="continuous"
)
# Create a wgpu device
adapter = wgpu.gpu.request_adapter_sync(power_preference="high-performance")
device = adapter.request_device_sync()
imgui_renderer = ImguiRenderer(device, canvas)
def create_texture_and_upload(data: np.ndarray) -> int:
# crates a GPUTexture and uploads it
# create a GPUTexture
texture = device.create_texture(
size=(data.shape[1], data.shape[0], 4),
usage=wgpu.TextureUsage.COPY_DST | wgpu.TextureUsage.TEXTURE_BINDING,
dimension=wgpu.TextureDimension.d2,
format=wgpu.TextureFormat.rgba8unorm,
mip_level_count=1,
sample_count=1,
)
# upload to the GPU
device.queue.write_texture(
{"texture": texture, "mip_level": 0, "origin": (0, 0, 0)},
data,
{"offset": 0, "bytes_per_row": data.shape[1] * 4},
(data.shape[1], data.shape[0], 1),
)
# get a view
texture_view = texture.create_view()
# register the texture with backend
return imgui_renderer.backend.register_texture(texture_view)
# list of colormaps that we will display in the picker
cmaps = ["viridis", "plasma", "turbo", "spring", "winter", "bwr", "gnuplot2"]
cmap_data = dict()
# creates texture for each colormap, uploads to the GPU, stores ids so we can display them in imgui
for name in cmaps:
# creates LUT
data = Colormap(name)(np.linspace(0, 1)) * 255
# vstack it so we have 2 rows to make a Texture, an array of shape [2, 255, 3], [rows, cols, RGB]
tex_ref = create_texture_and_upload(np.vstack([[data]] * 2).astype(np.uint8))
# store the texture
cmap_data[name] = tex_ref
current_cmap = cmaps[0]
def update_gui():
global current_cmap
imgui.set_next_window_size((175, 0), imgui.Cond_.appearing)
imgui.set_next_window_pos((0, 20), imgui.Cond_.appearing)
imgui.begin("window", None)
# make the cmap images display height similar to the text height so that it looks nice
texture_height = imgui.get_font_size() - 2
# add the items for the picker
for cmap_name, tex_ref in cmap_data.items():
# text part of each item
_clicked, enabled = imgui.menu_item(
cmap_name, "", p_selected=current_cmap == cmap_name
)
imgui.same_line()
# the image part of each item, give it the texture id
imgui.push_style_color(imgui.Col_.border, (1.0, 1.0, 1.0, 1.0))
imgui.push_style_var(imgui.StyleVar_.image_border_size, 1.0)
imgui.image(tex_ref, image_size=(50, texture_height))
imgui.pop_style_var()
imgui.pop_style_color()
if enabled:
current_cmap = cmap_name
imgui.end()
imgui_renderer.set_gui(update_gui)
if __name__ == "__main__":
canvas.request_draw(imgui_renderer.render)
loop.run()