chickensources/
lib.rs

1#![warn(clippy::pedantic)]
2#![warn(clippy::nursery)]
3
4mod body;
5mod subbody;
6mod title;
7mod utils;
8mod via;
9
10use image::{imageops, DynamicImage, Rgba, RgbaImage};
11
12const BLACK: Rgba<u8> = Rgba([0, 0, 0, 255]);
13const TRANSPARENT: Rgba<u8> = Rgba([0, 0, 0, 0]);
14
15/// Creates a graphic with the given title, body, subbody, and via.
16#[must_use]
17pub fn generate_graphic(
18    title: &str,
19    body: Option<&str>,
20    subbody: Option<&str>,
21    via: Option<&str>,
22    image: &DynamicImage,
23) -> DynamicImage {
24    let title = title.trim().to_uppercase();
25    let body = body.map(|body| body.trim().to_uppercase());
26    let subbody = subbody.map(|subbody| subbody.trim().to_uppercase());
27    let via = via.map(|via| via.trim().to_uppercase());
28
29    let mut img = background(image);
30
31    title::draw(&mut img, &title);
32
33    if let Some(body) = &body {
34        body::draw(&mut img, body);
35    }
36
37    if let Some(subbody) = &subbody {
38        subbody::draw(&mut img, subbody);
39    }
40
41    if let Some(via) = &via {
42        via::draw(&mut img, via);
43    }
44
45    img
46}
47
48fn background(img: &DynamicImage) -> DynamicImage {
49    let photo = {
50        let (img_width, img_height) = (img.width(), img.height());
51
52        let aspect_ratio = 3.0 / 2.0;
53
54        let (width, height) = if f64::from(img_width) > f64::from(img_height) * aspect_ratio {
55            (img_height * 3 / 2, img_height)
56        } else {
57            (img_width, img_width / 3 * 2)
58        };
59
60        let x = (img_width - width) / 2;
61        let y = (img_height - height) / 2;
62
63        img.crop_imm(x, y, width, height)
64    };
65
66    let mut img =
67        DynamicImage::ImageRgba8(RgbaImage::from_pixel(photo.width(), photo.width(), BLACK));
68
69    imageops::overlay(&mut img, &photo, 0, 0);
70
71    let mut img = img.thumbnail_exact(1024, 1024);
72
73    let side_length = img.height();
74
75    let overlay_height = utils::div_ceil(side_length, 3);
76    let gradient = {
77        let mut gradient = RgbaImage::new(side_length, overlay_height);
78        imageops::vertical_gradient(&mut gradient, &TRANSPARENT, &BLACK);
79
80        gradient
81    };
82
83    imageops::overlay(&mut img, &gradient, 0, overlay_height.into());
84
85    img
86}