use image::io::Reader as ImageReader;
use image::{ImageBuffer, Rgb, DynamicImage};
use crate::tags::SurgeryStep;
use std::io::{self, Write};
#[derive(Debug)]
struct RgbIndexes {
red: usize,
green: usize,
blue: usize,
}
fn calculate_rgb_index(x: usize, y: usize, total_width: usize, total_height: usize) -> RgbIndexes {
RgbIndexes {
red: 0 * total_height * total_width + y * total_width + x,
green: 1 * total_height * total_width + y * total_width + x,
blue: 2 * total_height * total_width + y * total_width + x,
}
}
pub fn read_rgb_image(path: String, height: usize, width: usize) -> Vec<u8> {
let depth: usize = 3;
let img: DynamicImage = ImageReader::open(path).unwrap().decode().unwrap();
let resized_img: DynamicImage = img.resize_exact(width as u32, height as u32, image::imageops::FilterType::Nearest);
let rgb_img: ImageBuffer<Rgb<u8>, Vec<u8>> = resized_img.to_rgb8();
let mut raw_data = vec![0u8; depth * height * width];
for chunk in rgb_img.enumerate_pixels() {
let x: u32 = chunk.0;
let y: u32 = chunk.1;
let pixel: &Rgb<u8> = chunk.2;
let indexes = calculate_rgb_index(x as usize, y as usize, width, height);
raw_data[indexes.red as usize] = pixel[0]; raw_data[indexes.green as usize] = pixel[1]; raw_data[indexes.blue as usize] = pixel[2]; }
raw_data
}
pub fn write_frame_to_std_out(data: Vec<u8>, tag: SurgeryStep) {
let stdout = io::stdout();
let mut handle = stdout.lock();
handle.write_all(&(tag.to_u8() as u16).to_le_bytes()).unwrap();
handle.write_all(&(data.len() as u32).to_le_bytes()).unwrap();
for byte in data {
handle.write_all(&(byte as u16).to_le_bytes()).unwrap();
}
handle.flush().unwrap();
}
#[cfg(test)]
mod tests {
use super::*;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct DummyJson {
data: Vec<u8>,
}
#[test]
fn test_read_image() {
let _data = read_rgb_image("./data_stash/images/169_6300.jpg".to_string(), 480, 853);
}
#[test]
fn test_calculate_rgb_index() {
let total_height = 5;
let total_width = 10;
let indexes = calculate_rgb_index(0, 0, total_width, total_height);
assert_eq!(&0, &indexes.red);
assert_eq!(&50, &indexes.green);
assert_eq!(&100, &indexes.blue);
let indexes = calculate_rgb_index(1, 0, total_width, total_height);
assert_eq!(&1, &indexes.red);
assert_eq!(&51, &indexes.green);
assert_eq!(&101, &indexes.blue);
let indexes = calculate_rgb_index(2, 0, total_width, total_height);
assert_eq!(&2, &indexes.red);
assert_eq!(&52, &indexes.green);
assert_eq!(&102, &indexes.blue);
let indexes = calculate_rgb_index(0, 1, total_width, total_height);
assert_eq!(&10, &indexes.red);
assert_eq!(&60, &indexes.green);
assert_eq!(&110, &indexes.blue);
let indexes = calculate_rgb_index(0, 2, total_width, total_height);
assert_eq!(&20, &indexes.red);
assert_eq!(&70, &indexes.green);
assert_eq!(&120, &indexes.blue);
}
#[test]
fn test_test_calculate_rgb_index_quality_control() {
let raw_data = std::fs::read_to_string("./data_stash/images/dummy_rgb_data.json").unwrap();
let data: DummyJson = serde_json::from_str(&raw_data).unwrap();
let total_height = 5;
let total_width = 10;
let index = calculate_rgb_index(0, 0, total_width, total_height);
assert_eq!(&data.data[index.red], &111); assert_eq!(&data.data[index.green], &208); assert_eq!(&data.data[index.blue], &12);
let index = calculate_rgb_index(5, 3, total_width, total_height);
assert_eq!(&data.data[index.red], &65);
assert_eq!(&data.data[index.green], &7);
assert_eq!(&data.data[index.blue], &193);
let index = calculate_rgb_index(8, 2, total_width, total_height);
assert_eq!(&data.data[index.red], &253);
assert_eq!(&data.data[index.green], &133);
assert_eq!(&data.data[index.blue], &115);
}
}