80 lines
2.6 KiB
Rust
80 lines
2.6 KiB
Rust
use crate::{Image, RawImage};
|
|
|
|
fn average(data: &[u16], indexes: impl Iterator<Item = i64>) -> 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
|
|
}
|
|
|
|
pub fn linear_demosaic(raw_image: RawImage) -> Image<u16> {
|
|
match raw_image.cfa_pattern {
|
|
[0, 1, 1, 2] => linear_demosaic_rggb(raw_image),
|
|
_ => todo!(),
|
|
}
|
|
}
|
|
|
|
fn linear_demosaic_rggb(mut raw_image: RawImage) -> Image<u16> {
|
|
let width = raw_image.width as i64;
|
|
let height = raw_image.height as i64;
|
|
|
|
for row in 0..height {
|
|
let row_by_width = row * width;
|
|
|
|
for col in 0..width {
|
|
let pixel_index = row_by_width + col;
|
|
|
|
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];
|
|
|
|
match (row % 2 == 0, col % 2 == 0) {
|
|
(true, true) => {
|
|
let indexes = cross_indexes.iter().map(|x| 3 * x + 1);
|
|
raw_image.data[3 * (pixel_index as usize) + 1] = average(&raw_image.data, indexes);
|
|
|
|
let indexes = diagonal_indexes.iter().map(|x| 3 * x + 2);
|
|
raw_image.data[3 * (pixel_index as usize) + 2] = average(&raw_image.data, indexes);
|
|
}
|
|
(true, false) => {
|
|
let indexes = horizontal_indexes.iter().map(|x| 3 * x);
|
|
raw_image.data[3 * (pixel_index as usize)] = average(&raw_image.data, indexes);
|
|
|
|
let indexes = vertical_indexes.iter().map(|x| 3 * x + 2);
|
|
raw_image.data[3 * (pixel_index as usize) + 2] = average(&raw_image.data, indexes);
|
|
}
|
|
(false, true) => {
|
|
let indexes = vertical_indexes.iter().map(|x| 3 * x);
|
|
raw_image.data[3 * (pixel_index as usize)] = average(&raw_image.data, indexes);
|
|
|
|
let indexes = horizontal_indexes.iter().map(|x| 3 * x + 2);
|
|
raw_image.data[3 * (pixel_index as usize) + 2] = average(&raw_image.data, indexes);
|
|
}
|
|
(false, false) => {
|
|
let indexes = cross_indexes.iter().map(|x| 3 * x + 1);
|
|
raw_image.data[3 * (pixel_index as usize) + 1] = average(&raw_image.data, indexes);
|
|
|
|
let indexes = diagonal_indexes.iter().map(|x| 3 * x);
|
|
raw_image.data[3 * (pixel_index as usize)] = average(&raw_image.data, indexes);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Image {
|
|
channels: 3,
|
|
data: raw_image.data,
|
|
width: raw_image.width,
|
|
height: raw_image.height,
|
|
rgb_to_camera: raw_image.rgb_to_camera,
|
|
histogram: None,
|
|
}
|
|
}
|