Skip to content

Commit 93fb708

Browse files
committed
docs: add frosted glass blur and graphics pipeline animated showcase GIF to README
1 parent 078440e commit 93fb708

4 files changed

Lines changed: 87 additions & 0 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ gui.render(&mut display)?;
5050

5151
## Visual Showcase
5252

53+
### Accelerated Graphics Pipeline & Frosted Glass Blur
54+
![Frosted glass and graphics pipeline showcase](docs/screenshots/frosted_glass_pipeline.gif)
55+
5356
### Tactile Cinematic Motion & Transitions
5457
![Animation and transition showcase](docs/screenshots/motion.gif)
5558

167 KB
Loading

examples/basics/graphics_pipeline_showcase.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ fn render_scene<D: DrawTarget<Color = Rgb565> + PixelRead>(
133133
fn main() {
134134
println!("=== embedded-gui: Graphics Pipeline Showcase ===");
135135

136+
if std::env::args().any(|a| a == "--record-gif") || std::env::var("RECORD_GIF").is_ok() {
137+
record_frames();
138+
return;
139+
}
140+
136141
let res = std::panic::catch_unwind(|| {
137142
run_interactive();
138143
});
@@ -144,6 +149,37 @@ fn main() {
144149
}
145150
}
146151

152+
fn record_frames() {
153+
let out_dir = std::path::Path::new("target/pipeline_frames");
154+
let _ = std::fs::create_dir_all(out_dir);
155+
156+
let mut fb = Framebuffer::<FB_SIZE>::new(W, H);
157+
let total_frames = 80;
158+
println!(
159+
"Recording {} frames to target/pipeline_frames...",
160+
total_frames
161+
);
162+
163+
for f in 0..total_frames {
164+
render_scene(&mut fb, f, 160).unwrap();
165+
166+
// Convert RGB565 to RGB888 bytes
167+
let mut rgb888 = Vec::with_capacity((W * H * 3) as usize);
168+
for p in fb.pixels() {
169+
let r = (p.r() << 3) | (p.r() >> 2);
170+
let g = (p.g() << 2) | (p.g() >> 4);
171+
let b = (p.b() << 3) | (p.b() >> 2);
172+
rgb888.push(r);
173+
rgb888.push(g);
174+
rgb888.push(b);
175+
}
176+
177+
let filename = out_dir.join(format!("frame_{:03}.raw", f));
178+
std::fs::write(filename, &rgb888).unwrap();
179+
}
180+
println!("Frame recording complete!");
181+
}
182+
147183
fn run_interactive() {
148184
let mut fb = Framebuffer::<FB_SIZE>::new(W, H);
149185
let mut display = SimulatorDisplay::<Rgb565>::new(Size::new(W, H));

scripts/generate_screenshots.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Generate animated GIFs and screenshots for embedded-gui documentation.
4+
"""
5+
6+
import os
7+
import subprocess
8+
from pathlib import Path
9+
from PIL import Image
10+
11+
W, H = 320, 240
12+
REPO_ROOT = Path(__file__).resolve().parent.parent
13+
FRAMES_DIR = REPO_ROOT / "target" / "pipeline_frames"
14+
OUTPUT_GIF = REPO_ROOT / "docs" / "screenshots" / "frosted_glass_pipeline.gif"
15+
16+
def main():
17+
print("1. Running showcase in record-frames mode...")
18+
subprocess.run(
19+
["cargo", "run", "--example", "graphics_pipeline_showcase", "--", "--record-gif"],
20+
cwd=REPO_ROOT,
21+
check=True,
22+
)
23+
24+
print("2. Compiling raw frames into animated GIF...")
25+
raw_files = sorted(FRAMES_DIR.glob("frame_*.raw"))
26+
if not raw_files:
27+
print("Error: No recorded frames found!")
28+
return
29+
30+
images = []
31+
for f in raw_files:
32+
raw_bytes = f.read_bytes()
33+
img = Image.frombytes("RGB", (W, H), raw_bytes)
34+
images.append(img)
35+
36+
OUTPUT_GIF.parent.mkdir(parents=True, exist_ok=True)
37+
images[0].save(
38+
OUTPUT_GIF,
39+
save_all=True,
40+
append_images=images[1:],
41+
duration=33, # ~30 fps
42+
loop=0,
43+
optimize=True,
44+
)
45+
print(f"-> Successfully generated {OUTPUT_GIF} ({len(images)} frames, {os.path.getsize(OUTPUT_GIF)} bytes)")
46+
47+
if __name__ == "__main__":
48+
main()

0 commit comments

Comments
 (0)