use crate::{Pixel, RawImage}; fn average(data: &[u16], indexes: impl Iterator) -> u16 { let mut sum = 0; let mut count = 0; for index in indexes { if index >= 0 && (index as usize) < data.len() { sum += data[index as usize] as u32; count += 1; } } (sum / count) as u16 } impl RawImage { pub fn linear_demosaic_iter(&self) -> impl Iterator + use<'_> { match self.cfa_pattern { [0, 1, 1, 2] => self.linear_demosaic_rggb_iter(), _ => todo!(), } } fn linear_demosaic_rggb_iter(&self) -> impl Iterator + use<'_> { let width = self.width as i64; let height = self.height as i64; (0..height).flat_map(move |row| { let row_by_width = row * width; (0..width).map(move |column| { let pixel_index = row_by_width + column; let vertical_indexes = [pixel_index + width, pixel_index - width]; let horizontal_indexes = [pixel_index + 1, pixel_index - 1]; let cross_indexes = [pixel_index + width, pixel_index - width, pixel_index + 1, pixel_index - 1]; let diagonal_indexes = [pixel_index + width + 1, pixel_index - width + 1, pixel_index + width - 1, pixel_index - width - 1]; let pixel_index = pixel_index as usize; match (row % 2 == 0, column % 2 == 0) { (true, true) => Pixel { values: [ self.data[pixel_index], average(&self.data, cross_indexes.into_iter()), average(&self.data, diagonal_indexes.into_iter()), ], row: row as usize, column: column as usize, }, (true, false) => Pixel { values: [ average(&self.data, horizontal_indexes.into_iter()), self.data[pixel_index], average(&self.data, vertical_indexes.into_iter()), ], row: row as usize, column: column as usize, }, (false, true) => Pixel { values: [ average(&self.data, vertical_indexes.into_iter()), self.data[pixel_index], average(&self.data, horizontal_indexes.into_iter()), ], row: row as usize, column: column as usize, }, (false, false) => Pixel { values: [ average(&self.data, diagonal_indexes.into_iter()), average(&self.data, cross_indexes.into_iter()), self.data[pixel_index], ], row: row as usize, column: column as usize, }, } }) }) } }