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, 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>, } 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 { 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::()) .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::>>(); 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> = (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); } }