1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| use image::{ImageBuffer, Rgb}; use std::f64::consts::{E, PI};
fn hsv_to_rgb(h: f64, s: f64, v: f64) -> Rgb<u8> { let c = v * s; let x = c * (1.0 - ((h / 60.0) % 2.0 - 1.0)).abs(); let m = v - c;
let (r, g, b) = match h { h if h < 60.0 => (c, x, 0.0), h if h < 120.0 => (x, c, 0.0), h if h < 180.0 => (0.0, c, x), h if h < 240.0 => (0.0, x, c), h if h < 300.0 => (x, 0.0, c), _ => (c, 0.0, x), };
Rgb([ ((r + m) * 255.0).clamp(0.0, 255.0) as u8, ((g + m) * 255.0).clamp(0.0, 255.0) as u8, ((b + m) * 255.0).clamp(0.0, 255.0) as u8, ]) }
fn generate_line_avatar(size: u32) -> ImageBuffer<Rgb<u8>, Vec<u8>> { let mut img = ImageBuffer::new(size, size); let center = (size as f64 / 2.0, size as f64 / 2.0); let max_radius = center.0 * 0.9;
for (x, y, pixel) in img.enumerate_pixels_mut() { let dx = x as f64 - center.0; let dy = y as f64 - center.1; let distance = (dx * dx + dy * dy).sqrt(); let angle = dy.atan2(dx) + PI;
let line_density = 2.0; let mut wave = (angle * line_density + distance * 0.1).sin();
wave += 0.6 * (angle * 15.0 + distance * 0.05).cos();
let threshold = 0.8 * (1.0 - distance / max_radius).powf(2.0); let is_line = wave.abs() > threshold;
let hue = (distance * 0.5 + angle * 180.0 / PI) % 360.0; let saturation = 0.8 - distance / max_radius * 0.3; let value = if is_line { 0.9 } else { 0.2 };
*pixel = hsv_to_rgb(hue, saturation, value); }
for x in 0..size { for y in 0..size { let dx = x as f64 - center.0; let dy = y as f64 - center.1; let distance = (dx * dx + dy * dy).sqrt();
if distance < 15.0 { let alpha = (1.0 - distance / 15.0).powf(2.0); let p = img.get_pixel_mut(x, y); p.0 = p.0.map(|c| (c as f64 * (1.0 - alpha) + 255.0 * alpha) as u8); } } }
img }
fn main() { let img = generate_line_avatar(1024); img.save("line_avatar.png").unwrap(); println!("线条头像已生成:line_avatar.png"); }
|