Since importing and displaying GIF is not natively supported in dearpygui, how would one go about to render and animate a GIF in dpg using the existing tools?
One can use imageio or Pillow to load all the frames of a GIF into memory. From there, the trick is to change the frame loaded into a texture using dpg.set_value
to the next gif frame, and then call dpg.render_dearpygui_frame()
to render the new frame into the window. Using time.sleep
, we can adjust the frame rate.
Here is a working example code to load, render and animate a GIF:
import dearpygui.dearpygui as dpg
import numpy as np
import imageio
import threading
import time
path_to_gif = "/path/to/your/gif/file.gif"
dpg.create_context()
dpg.create_viewport(title="Custom Title", width=600, height=800)
dpg.setup_dearpygui()
# Load the GIF using imageio
gif = imageio.mimread(path_to_gif)
# Function to adapt numpy image to dpg texture image
def adapt_frame_to_dpg(frame: np.ndarray) -> np.ndarray:
data = frame.ravel() # Flatten the data
data = np.asarray(data, dtype="float32") # Change data type to 32-bit floats
return np.true_divide(data, 255.0) # Normalize the image data
# Get the dimensions of the GIF
frame_width, frame_height = gif[0].shape[1], gif[0].shape[0]
frame = gif[0][:, :, :3] # Extract RGB channels
texture_data = adapt_frame_to_dpg(frame)
with dpg.texture_registry(show=False):
dpg.add_raw_texture(
frame_width,
frame_height,
texture_data,
tag="texture_tag",
format=dpg.mvFormat_Float_rgb,
)
with dpg.window(label="Animating a gif !"):
with dpg.drawlist(400, 265):
dpg.draw_image("texture_tag", (0, 0), (400, 265))
dpg.show_viewport()
frame_index = 0
# The animation function : Update the texture with the next frame of the GIF
def animate_gifs() -> None:
global frame_index, gif
desired_fps = 30
frame = gif[frame_index % len(gif)][:, :, :3] # Extract RGB channels
texture_data = adapt_frame_to_dpg(frame)
dpg.set_value("texture_tag", texture_data)
frame_index += 1
time.sleep(1 / desired_fps)
animation_thread = None
while dpg.is_dearpygui_running():
dpg.render_dearpygui_frame()
# Put the animation work in a thread to not slow the eventual inputs
if (
animation_thread != None
and not animation_thread.is_alive()
or animation_thread == None
):
animation_thread = threading.Thread(target=animate_gifs)
animation_thread.start()
dpg.destroy_context()
The code also works for videos, you only need to adapt the loading part:
max_frames = 500 # Needed as imageio has a threshold on the amount of loadable data
video = imageio.get_reader(path_to_video)
gif = []
for f in range(min(max_frames, video.count_frames())):
gif.append(video.get_data(f))