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
79
80
81
82
//! text render

use image::{DynamicImage, ImageBuffer, Rgba, Pixel};
use rusttype::{point, Font, Scale};

pub fn render(text: &str) -> ImageBuffer<Rgba<u8>, Vec<u8>> {
    let padding = 5;
    let font_size = 32.0;

    // Load the font
    let font_data = include_bytes!("../OCRB.ttf");
    // This only succeeds if collection consists of one font
    let font = Font::from_bytes(font_data as &[u8]).expect("Error constructing Font");

    // The font size to use
    let scale = Scale::uniform(font_size);

    // The text to render
    //let text = "This is RustType rendered into a png!";

    // Use a dark red colour
    let colour = (255, 255, 255);

    let v_metrics = font.v_metrics(scale);

    // layout the glyphs in a line with 20 pixels padding
    let glyphs: Vec<_> = font
        .layout(
            text,
            scale,
            point(padding as f32, padding as f32 + v_metrics.ascent),
        )
        .collect();

    // work out the layout size
    let glyphs_height = (v_metrics.ascent - v_metrics.descent).ceil() as u32;
    let glyphs_width = {
        let min_x = glyphs
            .first()
            .map(|g| g.pixel_bounding_box().unwrap().min.x)
            .unwrap();
        let max_x = glyphs
            .last()
            .map(|g| g.pixel_bounding_box().unwrap().max.x)
            .unwrap();
        (max_x - min_x) as u32
    };

    // Create a new rgba image with some padding
    let mut image = DynamicImage::new_rgba8(
        glyphs_width + 2 * padding + (font_size / 4.0) as u32,
        glyphs_height + 2 * padding,
    )
    .to_rgba();

    // Black background
    for p in image.pixels_mut() {
        *p = Rgba([0, 0, 0, 255]);
    }

    // Loop through the glyphs in the text, positing each one on a line
    for glyph in glyphs {
        if let Some(bounding_box) = glyph.pixel_bounding_box() {
            // Draw the glyph into the image per-pixel by using the draw closure
            glyph.draw(|x, y, v| {
                image.get_pixel_mut(
                    // Offset the position by the glyph bounding box
                    x + bounding_box.min.x as u32,
                    y + bounding_box.min.y as u32,
                ).blend(
                    // Turn the coverage into an alpha value
                    &Rgba([colour.0, colour.1, colour.2, (v * 255.0) as u8]),
                );
            });
        }
    }

    // Save the image to a png file
    //image.save("image_example.png").unwrap();
    //println!("Generated: image_example.png");
    image
}