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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
use gifed::{writer::ImageBuilder, Gif, StandardGif};
#[rustfmt::skip]
pub const DARK_PALETTE: &[u8] = &[
0, 0, 0, // Background - Black
192, 192, 192, // Graphline - Mostly White
64, 64, 64, // Gridlines - Dark gray
32, 32, 32, // Minor Gridlines - Darker gray
144, 144, 255, // Primary 2 Colour - Blue
48, 192, 48, // Secondary 2 Colour - Green
96, 96, 224, // Primary Underfill - Light Blue
48, 128, 48, // Secondary Underfill - Lesser Green
];
const BACKGROUND: u8 = 0;
const LINE: u8 = 1;
const GRIDLINE: u8 = 2;
const MINOR_GRIDLINE: u8 = 3;
const LINE1: u8 = 4;
const LINE2: u8 = 5;
const LINE1_FILL: u8 = 6;
const LINE2_FILL: u8 = 7;
const WIDTH: usize = 256;
const HEIGHT: usize = 160;
const SIZE: usize = WIDTH * HEIGHT;
pub fn make_1line(min: usize, max: usize, values: &[usize]) -> Gif {
let range = max - min;
// this assumes a range of values that is >1 per pixel
let vpp = range / HEIGHT;
let mut raster = vec![0; SIZE];
draw_grid(&mut raster);
draw_line(&mut raster, values, vpp, LINE);
let mut standard = Gif::new(WIDTH as u16, HEIGHT as u16);
standard.set_palette(Some(DARK_PALETTE[0..12].try_into().unwrap()));
standard.push(
ImageBuilder::new(WIDTH as u16, HEIGHT as u16)
.build(raster)
.unwrap(),
);
standard
}
pub fn make_2line(min: usize, max: usize, values1: &[usize], values2: &[usize]) -> Gif {
let range = max - min;
// this assumes a range of values that is >1 per pixel
let vpp = range / HEIGHT;
let mut raster = vec![0; SIZE];
draw_grid(&mut raster);
draw_line_underfill(&mut raster, values1, vpp, LINE1, LINE1_FILL);
draw_line_underfill(&mut raster, values2, vpp, LINE2, LINE2_FILL);
let mut standard = Gif::new(WIDTH as u16, HEIGHT as u16);
standard.set_palette(Some(DARK_PALETTE.try_into().unwrap()));
standard.push(
ImageBuilder::new(WIDTH as u16, HEIGHT as u16)
.build(raster)
.unwrap(),
);
standard
}
fn draw_grid(raster: &mut [u8]) {
// Draw Divisions
// we want a gridline every 16 pixels, but not the bottom
// or top, so only 8.
for div in 1..=9 {
let y_val = div * 16;
let grid = if div % 2 == 0 {
GRIDLINE
} else {
MINOR_GRIDLINE
};
for x in 0..WIDTH {
raster[y_val * WIDTH + x] = grid;
}
}
}
fn draw_line(raster: &mut [u8], values: &[usize], vpp: usize, colour: u8) {
// Draw Line
// this will be discontinuous and i think that's okay. we
// could make it a proper line by keeping track what value
// was last and drawing the whole vertical there
for (x, value) in values.iter().enumerate() {
let value_height = value / vpp;
if value_height > (HEIGHT - 1) {
continue;
}
let y_val = (HEIGHT - 1) - value_height;
raster[y_val * WIDTH + x] = colour;
}
}
fn draw_line_underfill(
raster: &mut [u8],
values: &[usize],
vpp: usize,
colour: u8,
colour_fill: u8,
) {
for (x, value) in values.iter().enumerate() {
let value_height = value / vpp;
if value_height > (HEIGHT - 1) {
continue;
}
let y_val = (HEIGHT - 1) - value_height;
for y in y_val + 1..HEIGHT {
raster[y * WIDTH + x] = colour_fill;
}
raster[y_val * WIDTH + x] = colour;
}
}
|