chickensources 0.1.2

generate chickensources graphics
Documentation
#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]

mod body;
mod subbody;
mod title;
mod utils;
mod via;

use image::{imageops, DynamicImage, Rgba, RgbaImage};

const BLACK: Rgba<u8> = Rgba([0, 0, 0, 255]);
const TRANSPARENT: Rgba<u8> = Rgba([0, 0, 0, 0]);

/// Creates a graphic with the given title, body, subbody, and via.
#[must_use]
pub fn generate_graphic(
    title: &str,
    body: Option<&str>,
    subbody: Option<&str>,
    via: Option<&str>,
    image: &DynamicImage,
) -> DynamicImage {
    let title = title.trim().to_uppercase();
    let body = body.map(|body| body.trim().to_uppercase());
    let subbody = subbody.map(|subbody| subbody.trim().to_uppercase());
    let via = via.map(|via| via.trim().to_uppercase());

    let mut img = background(image);

    title::draw(&mut img, &title);

    if let Some(body) = &body {
        body::draw(&mut img, body);
    }

    if let Some(subbody) = &subbody {
        subbody::draw(&mut img, subbody);
    }

    if let Some(via) = &via {
        via::draw(&mut img, via);
    }

    img
}

fn background(img: &DynamicImage) -> DynamicImage {
    let photo = {
        let (img_width, img_height) = (img.width(), img.height());

        let aspect_ratio = 3.0 / 2.0;

        let (width, height) = if f64::from(img_width) > f64::from(img_height) * aspect_ratio {
            (img_height * 3 / 2, img_height)
        } else {
            (img_width, img_width / 3 * 2)
        };

        let x = (img_width - width) / 2;
        let y = (img_height - height) / 2;

        img.crop_imm(x, y, width, height)
    };

    let mut img =
        DynamicImage::ImageRgba8(RgbaImage::from_pixel(photo.width(), photo.width(), BLACK));

    imageops::overlay(&mut img, &photo, 0, 0);

    let mut img = img.thumbnail_exact(1024, 1024);

    let side_length = img.height();

    let overlay_height = utils::div_ceil(side_length, 3);
    let gradient = {
        let mut gradient = RgbaImage::new(side_length, overlay_height);
        imageops::vertical_gradient(&mut gradient, &TRANSPARENT, &BLACK);

        gradient
    };

    imageops::overlay(&mut img, &gradient, 0, overlay_height.into());

    img
}