1use std::path::Path;
2use std::sync::atomic::{AtomicI64, Ordering};
3
4use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
5
6use tof_image::RAW_FILE_SIZE;
7
8use crate::helper::replace_extension;
9use crate::tof_image::TofImage;
10
11pub mod helper;
12mod image_meta_data;
13mod tof_image;
14
15pub fn convert_depth_infrared(source_file: String, keep_name: bool, alpha: f64, beta: f64) {
22 let path = Path::new(&source_file);
23
24 let depth_file;
25 let infrared_file;
26
27 if keep_name {
28 infrared_file = replace_extension(&source_file, ".png");
29 depth_file = replace_extension(&source_file, ".tiff");
30 } else {
31 infrared_file = path
33 .parent()
34 .unwrap()
35 .join("grey.png")
36 .to_string_lossy()
37 .to_string();
38 depth_file = path
39 .parent()
40 .unwrap()
41 .join("depth.tiff")
42 .to_string_lossy()
43 .to_string();
44 }
45
46 let bytes = std::fs::read(path).unwrap_or_else(|_| panic!("File '{}' not found!", source_file));
47 let tof_image = convert_image_buffer(&bytes, true, true);
48
49 tof_image.write_depth_image(&depth_file);
51 tof_image.write_bw_image(&infrared_file, alpha, beta);
52}
53
54pub fn convert_infrared(source_file: String, keep_name: bool, alpha: f64, beta: f64) {
55 let path = Path::new(&source_file);
56
57 let infrared_file = if keep_name {
58 replace_extension(&source_file, ".png")
59 } else {
60 path.parent()
62 .unwrap()
63 .join("grey.png")
64 .to_string_lossy()
65 .to_string()
66 };
67
68 let bytes = std::fs::read(path).unwrap_or_else(|_| panic!("File '{}' not found!", source_file));
69 let tof_image = convert_image_buffer(&bytes, true, true);
70
71 tof_image.write_bw_image(&infrared_file, alpha, beta);
73}
74
75pub fn convert_depth(source_file: String, target_file: String) {
76 let path = Path::new(&source_file);
77 let bytes = std::fs::read(path).unwrap();
78
79 let tof_image = convert_image_buffer(&bytes, true, false);
80
81 tof_image.write_depth_image(target_file.as_str());
83}
84
85pub fn convert_image_buffer(
87 raw_data: &[u8],
88 decode_depth: bool,
89 decode_infrared: bool,
90) -> TofImage {
91 if raw_data.len() != RAW_FILE_SIZE {
93 panic!("Byte image has wrong length!");
94 }
95
96 let mut image = TofImage::decode_image(raw_data, decode_depth, decode_infrared, false);
97
98 if decode_infrared {
99 image.get_meta_data();
100 }
101
102 image
103}
104
105pub fn read_image_to_buffer(source_file: String) -> TofImage {
107 let path = Path::new(&source_file);
108
109 if !path.is_file() {
110 panic!("Source must be a file!");
111 }
112
113 let bytes = std::fs::read(path).unwrap();
114 convert_image_buffer(&bytes, true, true)
115}
116
117pub fn convert_folder(
118 source: String,
119 keep_names: bool,
120 create_infrared: bool,
121 depth_skip: bool,
122 alpha: f64,
123 beta: f64,
124 overwrite: bool,
125) {
126 let files_to_convert = helper::find_files(source, ".raw");
127 println!("Converting {} raw files.", files_to_convert.len());
128
129 if !depth_skip && !create_infrared {
131 files_to_convert.par_iter().for_each(|p| {
132 if overwrite || !Path::new(&replace_extension(p, ".tiff")).exists() {
133 convert_depth(p.to_string(), replace_extension(&p.to_string(), ".tiff"))
134 }
135 });
136 } else if !depth_skip && create_infrared {
138 files_to_convert.par_iter().for_each(|p| {
139 if overwrite
140 || (!Path::new(&replace_extension(p, ".tiff")).exists()
141 || !Path::new(&replace_extension(p, ".png")).exists())
142 {
143 convert_depth_infrared(p.to_string(), keep_names, alpha, beta)
144 }
145 });
146 } else if depth_skip && create_infrared {
147 files_to_convert.par_iter().for_each(|p| {
148 if overwrite || !Path::new(&replace_extension(p, ".png")).exists() {
149 convert_infrared(p.to_string(), keep_names, alpha, beta)
150 }
151 });
152 } else {
153 println!("No conversion requested!!");
154 return;
155 }
156}
157
158pub fn read_folder_temperature(source: String) {
159 let files_to_convert = helper::find_files(source, ".raw");
160 println!("Reading {} raw files.", files_to_convert.len());
161
162 let cnt = AtomicI64::new(0);
163 let sum_ext = AtomicI64::new(0);
164 let sum_int = AtomicI64::new(0);
165
166 files_to_convert.par_iter().for_each(|p| {
167 let image = read_image_to_buffer(p.to_string());
168 cnt.fetch_add(1, Ordering::SeqCst);
172 sum_ext.fetch_add(image.meta.t_ext as i64, Ordering::SeqCst);
173 sum_int.fetch_add(image.meta.t_int as i64, Ordering::SeqCst);
174 });
175
176 let cnt_value = cnt.load(Ordering::SeqCst) as f32;
178 let sum_ext_value = sum_ext.load(Ordering::SeqCst) as f32;
179 let sum_int_value = sum_int.load(Ordering::SeqCst) as f32;
180
181 println!(
182 "Average temperature: Ext: {} Int: {}",
183 sum_ext_value / cnt_value,
184 sum_int_value / cnt_value
185 );
186}
187
188pub fn read_file_temperature(file: String) {
189 let image = read_image_to_buffer(file);
190 println!(
191 "File temperature: Ext: {} Int: {}",
192 image.meta.t_ext, image.meta.t_int
193 );
194}
195
196#[cfg(test)]
197mod tests {
198 use std::fs;
199 use std::path::Path;
200
201 use crate::{
202 convert_depth_infrared, convert_folder, convert_image_buffer, read_image_to_buffer,
203 };
204
205 #[test]
206 #[should_panic]
207 fn wrong_raw_image_size() {
208 let v: Vec<u8> = vec![0, 1, 2];
209 convert_image_buffer(&v, true, true);
210 }
211
212 #[test]
213 fn convert_raw_image() {
214 convert_depth_infrared("./data/data_hot.raw".to_string(), true, 0.1, 0.2);
215 }
216
217 #[test]
218 fn get_temperatures() {
219 let image_hot = read_image_to_buffer("./data/data_hot.raw".to_string());
220 assert_eq!(image_hot.meta.t_int, 71);
221 assert_eq!(image_hot.meta.t_ext, 51);
222 assert_eq!(image_hot.meta.exposure_time, 60000);
223
224 let image_cold = read_image_to_buffer("./data/data_cold.raw".to_string());
225 assert_eq!(image_cold.meta.t_int, 60);
226 assert_eq!(image_cold.meta.t_ext, 43);
227 assert_eq!(image_cold.meta.exposure_time, 60000);
228 }
229
230 #[test]
231 fn test_depth() {
232 let tof_image = read_image_to_buffer("./data/data_hot.raw".to_string());
233 let mut depth_sum: u32 = 0;
234
235 for d in tof_image.depth_image {
237 depth_sum += d as u32;
238 }
239 assert_eq!(depth_sum, 63723279);
240
241 let mut infrared_sum: u32 = 0;
242 for i in tof_image.infrared_image {
243 infrared_sum += i as u32;
244 }
245 assert_eq!(infrared_sum, 36893926);
246 }
247
248 #[test]
249 fn test_not_overwrite() {
250 let _ = fs::remove_file("./data/data_cold.png");
252 convert_folder("./data/".to_string(), true, true, false, 0.1, 0.2, false);
253
254 assert!(Path::new("./data/data_cold.png").exists());
255
256 let _ = fs::remove_file("./data/data_cold.tiff");
258 convert_folder("./data/".to_string(), true, false, false, 0.1, 0.2, false);
259
260 assert!(Path::new("./data/data_cold.tiff").exists());
261 }
262}