···1212 let height = img_rgb.height() as usize;
13131414 let mut right_rgb: ImageBuffer<Rgb<u8>, Vec<u8>> = ImageBuffer::new(width as u32, height as u32);
1515-1616- let bg = Rgb([64u8, 64u8, 64u8]);
1717- for pixel in right_rgb.pixels_mut() {
1818- *pixel = bg;
1919- }
1515+ let mut depth_buffer = vec![f32::NEG_INFINITY; width * height];
1616+ let mut filled = vec![false; width * height];
20172118 for y in 0..height {
2219 for x in 0..width {
···2522 let x_right = x as i32 - disparity;
26232724 if x_right >= 0 && x_right < width as i32 {
2828- if let Some(pixel) = img_rgb.get_pixel_checked(x as u32, y as u32) {
2929- right_rgb.put_pixel(x_right as u32, y as u32, *pixel);
2525+ let idx = y * width + x_right as usize;
2626+ if depth_val > depth_buffer[idx] {
2727+ depth_buffer[idx] = depth_val;
2828+ filled[idx] = true;
2929+ if let Some(pixel) = img_rgb.get_pixel_checked(x as u32, y as u32) {
3030+ right_rgb.put_pixel(x_right as u32, y as u32, *pixel);
3131+ }
3032 }
3133 }
3234 }
3335 }
34363535- fill_disocclusions(&mut right_rgb);
3737+ fill_disocclusions(&mut right_rgb, &filled, width, height);
36383739 let left_image = image.clone();
3840 let right_image = DynamicImage::ImageRgb8(right_rgb);
···6567 }
6668}
67696868-fn fill_disocclusions(image: &mut ImageBuffer<Rgb<u8>, Vec<u8>>) {
6969- let width = image.width() as usize;
7070- let height = image.height() as usize;
7171- let bg = Rgb([64u8, 64u8, 64u8]);
7272-7070+fn fill_disocclusions(
7171+ image: &mut ImageBuffer<Rgb<u8>, Vec<u8>>,
7272+ filled: &[bool],
7373+ width: usize,
7474+ height: usize,
7575+) {
7376 let original = image.clone();
74777578 for y in 0..height {
7679 for x in 0..width {
7777- let pixel = original.get_pixel(x as u32, y as u32);
7878- if pixel[0] == bg[0] && pixel[1] == bg[1] && pixel[2] == bg[2] {
7979- if let Some(nearest) = find_nearest_valid(&original, x, y, bg) {
8080- image.put_pixel(x as u32, y as u32, nearest);
8181- }
8080+ if filled[y * width + x] {
8181+ continue;
8282 }
8383- }
8484- }
8585-}
8686-8787-fn find_nearest_valid(
8888- image: &ImageBuffer<Rgb<u8>, Vec<u8>>,
8989- cx: usize,
9090- cy: usize,
9191- bg: Rgb<u8>,
9292-) -> Option<Rgb<u8>> {
9393- let width = image.width() as usize;
9494- let height = image.height() as usize;
9595-9696- for radius in 1..=20 {
9797- for dy in -(radius as i32)..=(radius as i32) {
9898- for dx in -(radius as i32)..=(radius as i32) {
9999- if dx.abs() != radius as i32 && dy.abs() != radius as i32 {
100100- continue;
8383+ // scan left to find nearest filled pixel on same row
8484+ let mut left_pixel = None;
8585+ for lx in (0..x).rev() {
8686+ if filled[y * width + lx] {
8787+ left_pixel = Some(*original.get_pixel(lx as u32, y as u32));
8888+ break;
10189 }
102102- let nx = (cx as i32 + dx) as usize;
103103- let ny = (cy as i32 + dy) as usize;
104104- if nx < width && ny < height {
105105- let pixel = image.get_pixel(nx as u32, ny as u32);
106106- if pixel[0] != bg[0] || pixel[1] != bg[1] || pixel[2] != bg[2] {
107107- return Some(*pixel);
108108- }
9090+ }
9191+ // scan right
9292+ let mut right_pixel = None;
9393+ for rx in (x + 1)..width {
9494+ if filled[y * width + rx] {
9595+ right_pixel = Some(*original.get_pixel(rx as u32, y as u32));
9696+ break;
10997 }
11098 }
9999+100100+ let fill = match (left_pixel, right_pixel) {
101101+ (Some(l), Some(_)) => l, // prefer left (background side in DIBR)
102102+ (Some(l), None) => l,
103103+ (None, Some(r)) => r,
104104+ (None, None) => continue,
105105+ };
106106+ image.put_pixel(x as u32, y as u32, fill);
111107 }
112108 }
113113-114114- None
115109}