use image::{GrayImage, Luma};
use crate::OccupancyGrid;
use crate::types::UNKNOWN;
pub fn occupancy_grid_to_image(grid: &OccupancyGrid) -> GrayImage {
let width = grid.width();
let height = grid.height();
let mut img = GrayImage::new(width, height);
for y_img in 0..height {
let y_grid = height - 1 - y_img;
for x in 0..width {
let value = grid
.get(glam::UVec2::new(x, y_grid))
.copied()
.unwrap_or(UNKNOWN);
let px = occupancy_to_gray(value);
img.put_pixel(x, y_img, Luma([px]));
}
}
img
}
fn occupancy_to_gray(value: i8) -> u8 {
if value == UNKNOWN {
return 205;
}
let v = (value as i16).clamp(0, 100);
let gray = 254 - ((v * 254) / 100);
gray as u8
}
#[cfg(test)]
mod tests {
use glam::UVec2;
use super::*;
use crate::MapInfo;
use crate::types::{FREE, OCCUPIED};
#[test]
fn occupancy_grid_to_image_maps_values_and_flips_y() {
let info = MapInfo {
width: 2,
height: 2,
resolution: 1.0,
..Default::default()
};
let grid = OccupancyGrid::init(info, vec![UNKNOWN, FREE, OCCUPIED, FREE]).unwrap();
assert_eq!(grid.get(UVec2::new(0, 0)).copied(), Some(UNKNOWN));
assert_eq!(grid.get(UVec2::new(0, 1)).copied(), Some(OCCUPIED));
let img = occupancy_grid_to_image(&grid);
assert_eq!(img.width(), 2);
assert_eq!(img.height(), 2);
let top_left = img.get_pixel(0, 0).0[0];
let bottom_left = img.get_pixel(0, 1).0[0];
assert_eq!(top_left, occupancy_to_gray(OCCUPIED));
assert_eq!(bottom_left, occupancy_to_gray(UNKNOWN));
let free_px = occupancy_to_gray(FREE);
let occ_px = occupancy_to_gray(OCCUPIED);
assert!(free_px > occ_px);
}
}