1use ndarray::*;
2use std::fs::File;
3use std::path::{Path, PathBuf};
4use tiff::decoder::DecodingResult;
5
6use crate::ThermogramTrait;
7
8#[derive(Clone, Debug)]
21pub struct TiffThermogram {
22 thermal: Array<f32, Ix2>,
23 file_path: PathBuf,
24}
25
26#[allow(dead_code)]
27impl TiffThermogram {
28 pub fn from_file(file_path: &Path) -> Option<Self> {
37 match Self::_read_thermal(file_path) {
38 Some(thermal) => {
39 return Some(Self {
40 thermal: thermal,
41 file_path: (*file_path).to_path_buf(),
42 });
43 }
44 _ => return None
45 }
46 }
47
48 fn _read_thermal(file_path: &Path) -> Option<Array<f32, Ix2>> {
49 return Self::_read_thermal_libtiff(file_path);
50 }
51
52 fn _read_thermal_libtiff(file_path: &Path) -> Option<Array<f32, Ix2>> {
53 let file = File::open(file_path).unwrap();
54 let mut tiff = tiff::decoder::Decoder::new(file).unwrap();
55 let tiff_dims = tiff.dimensions().unwrap();
56 let arr_dims = Dim((tiff_dims.1 as usize, tiff_dims.0 as usize));
57 let vec_to_ndarray = |values| {
58 let thermal = ndarray::ArrayBase::from(values);
59 let thermal = thermal.into_shape(arr_dims).unwrap();
60 thermal
61 };
62
63 match tiff.read_image() {
64 Ok(image) => match image {
65 DecodingResult::U8(values) => {
66 let f32_values: Vec<f32> =
67 values.into_iter().map(|integer| integer as f32).collect();
68
69 let thermal = vec_to_ndarray(f32_values);
70 Some(thermal)
71 },
72 DecodingResult::U16(values) => {
73 let f32_values: Vec<f32> =
74 values.into_iter().map(|integer| integer as f32).collect();
75
76 let thermal = vec_to_ndarray(f32_values);
77 let thermal = thermal - 27315.0;
78 Some(thermal / 100.0)
79 }
80 DecodingResult::U32(values) => {
81 let f32_values: Vec<f32> =
82 values.into_iter().map(|integer| integer as f32).collect();
83
84 let thermal = vec_to_ndarray(f32_values);
85 let thermal = thermal - 27315.0;
86 Some(thermal / 100.0)
87 }
88 DecodingResult::U64(values) => {
89 let f32_values: Vec<f32> =
90 values.into_iter().map(|integer| integer as f32).collect();
91
92 let thermal = vec_to_ndarray(f32_values);
93 let thermal = thermal - 27315.0;
94 Some(thermal / 100.0)
95 }
96 DecodingResult::F32(values) => {
97 Some(vec_to_ndarray(values))
98 }
99 DecodingResult::F64(values) => {
100 Some(vec_to_ndarray(values.iter().map(|v| *v as f32).collect()))
101 }
102 }
103 _ => None
104 }
105 }
106}
107
108impl ThermogramTrait for TiffThermogram {
109 fn thermal(&self) -> &Array<f32, Ix2> {
110 &self.thermal
111 }
112
113 fn optical(&self) -> Option<&Array<u8, Ix3>> {
114 None
115 }
116
117 fn identifier(&self) -> &str {
118 let file_name = self.file_path.file_name();
120 file_name.unwrap().to_str().unwrap()
121 }
122
123 fn path(&self) -> Option<&str> {
124 self.file_path.to_str()
125 }
126}