'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 |
