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
124
125
126
127
128
129
130
131
132
|
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: &[Option<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: &[Option<usize>],
values2: &[Option<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: &[Option<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, maybe) in values.iter().enumerate() {
if let Some(value) = maybe {
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: &[Option<usize>],
vpp: usize,
colour: u8,
colour_fill: u8,
) {
for (x, maybe) in values.iter().enumerate() {
if let Some(value) = maybe {
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;
}
}
}
|