visual_odometry_rs/misc/
helper.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5//! Miscellaneous helper functions that didn't fit elsewhere.
6
7use byteorder::{BigEndian, ReadBytesExt};
8use nalgebra::{DMatrix, Scalar};
9use png::{self, HasParameters};
10use std::{self, fs::File, io::Cursor, path::Path};
11
12/// Read a 16 bit gray png image from a file.
13pub fn read_png_16bits<P: AsRef<Path>>(
14    file_path: P,
15) -> Result<(usize, usize, Vec<u16>), png::DecodingError> {
16    // Load 16 bits PNG depth image.
17    let img_file = File::open(file_path)?;
18    let mut decoder = png::Decoder::new(img_file);
19    // Use the IDENTITY transformation because by default
20    // it will use STRIP_16 which only keep 8 bits.
21    // See also SWAP_ENDIAN that might be useful
22    //   (but seems not possible to use according to documentation).
23    decoder.set(png::Transformations::IDENTITY);
24    let (info, mut reader) = decoder.read_info()?;
25    let mut buffer = vec![0; info.buffer_size()];
26    reader.next_frame(&mut buffer)?;
27
28    // Transform buffer into 16 bits slice.
29    // if cfg!(target_endian = "big") ...
30    let mut buffer_u16 = vec![0; (info.width * info.height) as usize];
31    let mut buffer_cursor = Cursor::new(buffer);
32    buffer_cursor.read_u16_into::<BigEndian>(&mut buffer_u16)?;
33
34    // Return u16 buffer.
35    Ok((info.width as usize, info.height as usize, buffer_u16))
36}
37
38/// Map a function onto a matrix, at positions given by a mask.
39/// A default value is used at the other positions.
40pub fn zip_mask_map<T, U, F>(mat: &DMatrix<T>, mask: &DMatrix<bool>, default: U, f: F) -> DMatrix<U>
41where
42    T: Scalar,
43    U: Scalar,
44    F: Fn(T) -> U,
45{
46    mat.zip_map(mask, |x, is_true| if is_true { f(x) } else { default })
47}
48
49/// Compute the quotient and remainder of x/y both at the same time.
50pub fn div_rem<T>(x: T, y: T) -> (T, T)
51where
52    T: std::ops::Div<Output = T> + std::ops::Rem<Output = T> + Copy,
53{
54    (x / y, x % y)
55}