|
| 1 | +use exr::prelude::simple_image::*; |
| 2 | +use rayon::prelude::*; |
| 3 | +use config::Config; |
| 4 | + |
| 5 | +use std::fs; |
| 6 | +use std::time::Instant; |
| 7 | + |
| 8 | +use crate::util::generate_default_palette; |
| 9 | + |
| 10 | +pub struct RecolourEXR { |
| 11 | + palette: Vec<(u8, u8, u8)>, |
| 12 | + files: Vec<String>, |
| 13 | + iteration_division: f32 |
| 14 | +} |
| 15 | + |
| 16 | +impl RecolourEXR { |
| 17 | + pub fn new(settings: Config) -> Self { |
| 18 | + let palette = if let Ok(values) = settings.get_array("palette") { |
| 19 | + let palette = values.chunks_exact(3).map(|value| { |
| 20 | + // We assume the palette is in BGR rather than RGB |
| 21 | + (value[2].clone().into_int().unwrap() as u8, |
| 22 | + value[1].clone().into_int().unwrap() as u8, |
| 23 | + value[0].clone().into_int().unwrap() as u8) |
| 24 | + }).collect::<Vec<(u8, u8, u8)>>(); |
| 25 | + |
| 26 | + palette |
| 27 | + } else { |
| 28 | + generate_default_palette() |
| 29 | + }; |
| 30 | + let iteration_division = settings.get_float("iteration_division").unwrap_or(0.1) as f32; |
| 31 | + |
| 32 | + let paths = fs::read_dir("./output/").unwrap(); |
| 33 | + let mut exr_files = Vec::new(); |
| 34 | + |
| 35 | + for path in paths { |
| 36 | + let name = path.unwrap() |
| 37 | + .path() |
| 38 | + .to_owned() |
| 39 | + .to_str() |
| 40 | + .unwrap() |
| 41 | + .to_string(); |
| 42 | + |
| 43 | + if name.contains(".exr") { |
| 44 | + exr_files.push(name) |
| 45 | + } |
| 46 | + }; |
| 47 | + |
| 48 | + RecolourEXR { |
| 49 | + palette, |
| 50 | + files: exr_files, |
| 51 | + iteration_division |
| 52 | + } |
| 53 | + } |
| 54 | + |
| 55 | + pub fn colour(&self) { |
| 56 | + let colouring_time = Instant::now(); |
| 57 | + |
| 58 | + (&self.files).into_par_iter() |
| 59 | + .for_each(|exr_file| { |
| 60 | + let raw_data = Image::read_from_file(&exr_file, read_options::high()).unwrap(); |
| 61 | + |
| 62 | + let mut iterations = Vec::new(); |
| 63 | + let mut smooth = Vec::new(); |
| 64 | + |
| 65 | + for layer in &raw_data.layers { |
| 66 | + for channel in &layer.channels { |
| 67 | + match &channel.samples { |
| 68 | + Samples::F16(f16_vec) => { |
| 69 | + smooth = f16_vec.clone(); |
| 70 | + }, |
| 71 | + Samples::F32(_) => {}, |
| 72 | + Samples::U32(u32_vec) => { |
| 73 | + iterations = u32_vec.clone(); |
| 74 | + } |
| 75 | + }; |
| 76 | + } |
| 77 | + } |
| 78 | + |
| 79 | + let file_name = exr_file.split(".exr").collect::<Vec<_>>()[0]; |
| 80 | + let dimensions = raw_data.attributes.display_window.size; |
| 81 | + |
| 82 | + println!("{}.exr", file_name); |
| 83 | + |
| 84 | + let mut rgb_buffer = vec![0u8; iterations.len() * 3]; |
| 85 | + |
| 86 | + for i in 0..iterations.len() { |
| 87 | + if iterations[i] == 0xFFFFFFFF { |
| 88 | + rgb_buffer[3 * i] = 0u8; |
| 89 | + rgb_buffer[3 * i + 1] = 0u8; |
| 90 | + rgb_buffer[3 * i + 2] = 0u8; |
| 91 | + } else { |
| 92 | + let temp = (iterations[i] as f32 + smooth[i].to_f32()) / self.iteration_division; |
| 93 | + |
| 94 | + let temp2 = temp.floor() as usize % self.palette.len(); |
| 95 | + let temp3 = (temp as usize + 1) % self.palette.len(); |
| 96 | + let temp4 = temp.fract(); |
| 97 | + |
| 98 | + let colour1 = self.palette[temp2]; |
| 99 | + let colour2 = self.palette[temp3]; |
| 100 | + |
| 101 | + rgb_buffer[3 * i] = (colour1.0 as f32 + temp4 * (colour2.0 as f32 - colour1.0 as f32)) as u8; |
| 102 | + rgb_buffer[3 * i + 1] = (colour1.1 as f32 + temp4 * (colour2.1 as f32 - colour1.1 as f32)) as u8; |
| 103 | + rgb_buffer[3 * i + 2] = (colour1.2 as f32 + temp4 * (colour2.2 as f32 - colour1.2 as f32)) as u8; |
| 104 | + } |
| 105 | + } |
| 106 | + |
| 107 | + image::save_buffer(file_name.to_owned() + ".png", &rgb_buffer, dimensions.x() as u32, dimensions.y() as u32, image::ColorType::Rgb8).unwrap(); |
| 108 | + }); |
| 109 | + |
| 110 | + println!("Recolouring {} images took {} ms.", self.files.len(), colouring_time.elapsed().as_millis()); |
| 111 | + } |
| 112 | +} |
0 commit comments