waybar-collectd/draw/src/stacked.rs

100 lines
2.6 KiB
Rust
Raw Normal View History

2026-05-10 22:08:32 +02:00
use imageproc::{
drawing::draw_filled_rect_mut,
image::{Rgb, RgbImage},
rect::Rect,
};
pub struct StackedConfig {
pub width_px_per_sample: u32,
pub height_px: u32,
pub series: Vec<StackedSeriesConfig>,
pub max_samples: u32,
}
pub struct StackedSeriesConfig {
pub color: (u8, u8, u8),
}
pub struct StackedSeries<'a> {
pub config: &'a StackedConfig,
pub data: Vec<&'a Vec<f32>>,
}
pub fn stacked(graph: StackedSeries) -> RgbImage {
let mut image = RgbImage::new(
graph.config.width_px_per_sample * graph.config.max_samples,
graph.config.height_px as u32,
);
draw_scaled_graph(&mut image, &graph);
image
}
/// return scale factor to scale stacked series sum to range 0..1
fn get_scale(series: &Vec<&Vec<f32>>) -> f32 {
let len = series.iter().map(|s| s.len()).max().unwrap_or(0);
let max = (0..len)
.map(|i| series.iter().map(|s| s[i]).sum::<f32>())
.max_by(|f1, f2| f1.total_cmp(f2))
.unwrap_or(1f32);
1f32 / max
}
fn draw_scaled_graph(image: &mut RgbImage, graph: &StackedSeries) {
let scale = get_scale(&graph.data);
let colors = graph
.config
.series
.iter()
.map(|s| Rgb([s.color.0, s.color.1, s.color.2]))
.collect::<Vec<Rgb<u8>>>();
let mut x_offset = 0f32;
let mut series_idx = 0usize;
let rows = graph.data.len();
let cols = graph.data[0].len();
let transposed_series: Vec<Vec<f32>> = (0..cols)
.map(|col| (0..rows).map(|row| graph.data[row][col]).collect())
.collect();
for timeseries in transposed_series {
let mut y_offset = graph.config.height_px as f32;
for sample in timeseries.iter() {
println!("VAL {}", sample);
let color = colors[series_idx];
let height_px = (graph.config.height_px as f32) * sample * scale;
let rect = Rect::at(x_offset as i32, (y_offset - height_px) as i32)
.of_size(graph.config.width_px_per_sample, height_px as u32);
draw_filled_rect_mut(image, rect, color);
x_offset += graph.config.width_px_per_sample as f32;
y_offset -= height_px;
println!("rect: {:?}, height {}, yoff {}", rect, height_px, y_offset);
}
println!("BRK");
// FIXME:
// series_idx += 1;
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_get_scale() {
let conf = vec![
vec![1., 2., 3., 4., 5.],
vec![0., 1., 0., 0., 0.],
vec![0., 0., 0., 0., 5.],
];
assert_eq!(0, 1); // FIX
// assert_eq!(get_scale(&conf), 0.1);
}
}