//! Regenerate the PNG and multi-resolution Windows ICO from the editable SVG. use image::codecs::ico::{IcoEncoder, IcoFrame}; use std::{error::Error, fs::File}; fn main() -> Result<(), Box> { let tree = resvg::usvg::Tree::from_data( include_bytes!("../assets/icon.svg"), &resvg::usvg::Options::default(), )?; let mut frames = Vec::new(); for size in [16, 24, 32, 48, 64, 128, 256, 512] { let mut pixmap = resvg::tiny_skia::Pixmap::new(size, size).ok_or("invalid size")?; resvg::render( &tree, resvg::tiny_skia::Transform::from_scale(size as f32 / 512.0, size as f32 / 512.0), &mut pixmap.as_mut(), ); // tiny-skia stores premultiplied pixels; PNG and ICO need straight alpha. let mut rgba = pixmap.take(); for pixel in rgba.as_chunks_mut::<4>().0 { let alpha = pixel[3] as u32; for channel in &mut pixel[..3] { *channel = (*channel as u32 * 255 + alpha / 2) .checked_div(alpha) .unwrap_or(0) .min(255) as u8; } } if size == 512 { image::save_buffer( "assets/icon.png", &rgba, size, size, image::ColorType::Rgba8, )?; } else { frames.push(IcoFrame::as_png( &rgba, size, size, image::ExtendedColorType::Rgba8, )?); } } IcoEncoder::new(File::create("assets/icon.ico")?).encode_images(&frames)?; Ok(()) }