'rust: draw an image

I'm using actix-web to develop a function where the user can upload some data and then draw the data on a picture to generate a simple poster.

Here is some of my code:

#[derive(Debug, Deserialize)]
pub struct UserForm {
    name: String,
    age: u8,
}

#[post("/generate_user_poster")]
pub async fn generate_user_poster(form: web::Form<Info>) -> HttpResult {
    let form = query.into_inner();

    // This is pseudo code
    let img = image::load("bg.jpg");
    img.drawText(100, 100, form.name);
    img.drawText(100, 200, form.age);

    Ok(HttpResponse::Ok().body(img))
}

How can I draw text onto bg.jpg.



Solution 1:[1]

The most simple way to do this is probably using the imageproc crate. You can use draw_text_mut to add the text to the image in place like so:

#[post("/generate_user_poster")]
pub async fn generate_user_poster(form: web::Form<Info>) -> HttpResult {
    let form = query.into_inner();

    let mut img = image::load("bg.jpg");

    // Load a font.
    let font = Vec::from(include_bytes!("path/to/font.ttf") as &[u8]);
    let font = Font::try_from_vec(font).unwrap();

    let font_size = 40.0;
    let scale = Scale {
        x: font_size,
        y: font_size,
    };

    // Draw text to image and mutate it:
    draw_text_mut(
            &mut image, 
            Rgba([0u8, 0u8, 0u8, 255u8]), 
            100, // Your x position in pixels
            100, // Your y position in pixels
            scale, 
            &font, 
            form.name // Must be of type &str
    );

    draw_text_mut(
            &mut image, 
            Rgba([0u8, 0u8, 0u8, 255u8]), 
            200,
            200,
            scale, 
            &font, 
            form.age // Must be of type &str
    );
    

    Ok(HttpResponse::Ok().body(img))
}

Solution 2:[2]

This is a more complete example:

[dependencies]
image = "0.23.14"
imageproc = "0.22.0"
rusttype = "0.9.2"
use image::{imageops::overlay, GenericImageView, Rgba};
use imageproc::drawing::draw_text_mut;
use rusttype::{Font, Scale};

fn main() {
    let mut img = image::open("bg.jpg").unwrap();

    // Load a font.
    let font = Vec::from(include_bytes!("../arial.ttf") as &[u8]);
    let font = Font::try_from_vec(font).unwrap();

    let font_size = 40.0;
    let scale = Scale {
        x: font_size,
        y: font_size,
    };

    // draw text
    let name = "hello world";
    draw_text_mut(
        &mut img,
        Rgba([255u8, 0u8, 0u8, 255u8]),
        100, // x
        100, // y
        scale,
        &font,
        name, // Must be of type &str
    );

    // overlay another image on top of the image
    let tile = image::open("avatar.png").unwrap();
    let (w, h) = img.dimensions();
    let (w2, h2) = tile.dimensions();
    overlay(&mut img, &tile, w / 2 - w2 / 2, h / 2 - h2 / 2);

    // re-output a new image
    img.save("out.png").unwrap();
}
|-- arial.ttf
|-- avatar.png
|-- bg.jpg
|-- Cargo.toml
|-- out.png
|-- src
|   `-- main.rs
`-- target

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 frankenapps
Solution 2 januw a