use magick_rust::{DrawingWand, MagickError, MagickWand, PixelWand, magick_wand_genesis};
use std::fs;
use std::sync::Once;
static START: Once = Once::new();
const WIDTH: usize = 240;
const HEIGHT: usize = 120;
const FRAMES: usize = 6;
fn build_animation() -> Result<Vec<u8>, MagickError> {
START.call_once(|| {
magick_wand_genesis();
});
let mut wand = MagickWand::new();
for i in 0..FRAMES {
let mut frame = MagickWand::new();
let mut background = PixelWand::new();
background.set_color(&format!("hsl({}, 70%, 60%)", i * 360 / FRAMES))?;
frame.new_image(WIDTH, HEIGHT, &background)?;
frame.set_image_format("gif")?;
frame.set_image_delay(25)?;
wand.images_mut().append(&frame)?;
}
{
let images = wand.images();
println!("animation has {} frame(s)", images.count());
if let Some(first) = images.first() {
println!(
" first frame: {}x{}",
first.get_image_width(),
first.get_image_height()
);
}
if let Some(last) = images.last() {
println!(
" last frame: {}x{}, delay {} (1/100s)",
last.get_image_width(),
last.get_image_height(),
last.get_image_delay()
);
}
}
let mut ink = PixelWand::new();
ink.set_color("black")?;
let radius = 16.0;
wand.images_mut().try_for_each(|index, mut frame| {
let mut draw = DrawingWand::new();
draw.set_fill_color(&ink);
let progress = (index + 1) as f64 / (FRAMES + 1) as f64;
let cx = WIDTH as f64 * progress;
let cy = HEIGHT as f64 * progress;
draw.draw_circle(cx, cy, cx + radius, cy);
frame.draw_image(&draw)
})?;
wand.write_images_blob("gif")
}
fn main() {
match build_animation() {
Ok(bytes) => {
fs::write("gif-frames.gif", bytes).expect("write failed");
println!("wrote gif-frames.gif");
}
Err(err) => println!("error: {err}"),
}
}