dc_converter_tof/
lib.rs

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
15/// Convert a raw file to infrared and depth.
16///
17/// * `source_file` - Path of the file to convert.
18/// * `keep_name` - Keep original name instead of gray.png and depth.tiff.
19/// * `alpha` - Conversion factor Alpha.
20/// * `beta` - Conversion factor Beta.
21pub 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        // Default names:
32        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    // Write the files to flash:
50    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        // Default names:
61        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    // Write the files to flash:
72    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    // Write the files to flash:
82    tof_image.write_depth_image(target_file.as_str());
83}
84
85/// Convert an image from raw to all layers. "
86pub fn convert_image_buffer(
87    raw_data: &[u8],
88    decode_depth: bool,
89    decode_infrared: bool,
90) -> TofImage {
91    // Check image size for Opnous 8505C:
92    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
105/// Read an image to buffer
106pub 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    // Depth only:
130    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    // Depth and infrared:
137    } 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        // println!("{}", image.meta.t_int);
169
170        // Update count and sum atomically
171        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    // If you need to use the final values of `cnt` and `sum`
177    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        // TODO: Use map, check all!
236        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        // Don't care when not exists:
251        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        // Don't care when not exists:
257        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}