Skip to main content

oxihuman_export/
opacity_map_export.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5pub struct OpacityMap {
6    pub width: u32,
7    pub height: u32,
8    pub data: Vec<f32>,
9}
10
11pub fn new_opacity_map(w: u32, h: u32) -> OpacityMap {
12    OpacityMap {
13        width: w,
14        height: h,
15        data: vec![1.0; (w * h) as usize],
16    }
17}
18
19pub fn opacity_set(m: &mut OpacityMap, x: u32, y: u32, v: f32) {
20    if x < m.width && y < m.height {
21        m.data[(y * m.width + x) as usize] = v.clamp(0.0, 1.0);
22    }
23}
24
25pub fn opacity_get(m: &OpacityMap, x: u32, y: u32) -> f32 {
26    if x < m.width && y < m.height {
27        m.data[(y * m.width + x) as usize]
28    } else {
29        0.0
30    }
31}
32
33pub fn opacity_to_u8(m: &OpacityMap) -> Vec<u8> {
34    m.data.iter().map(|&v| (v * 255.0) as u8).collect()
35}
36
37pub fn opacity_mean(m: &OpacityMap) -> f32 {
38    if m.data.is_empty() {
39        return 0.0;
40    }
41    m.data.iter().sum::<f32>() / m.data.len() as f32
42}
43
44pub fn opacity_threshold_mask(m: &OpacityMap, thr: f32) -> Vec<bool> {
45    m.data.iter().map(|&v| v >= thr).collect()
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn test_new_opacity_map() {
54        /* dimensions and default data */
55        let m = new_opacity_map(4, 4);
56        assert_eq!(m.data.len(), 16);
57        assert!((m.data[0] - 1.0).abs() < 1e-6);
58    }
59
60    #[test]
61    fn test_opacity_set_get() {
62        /* set and get roundtrip */
63        let mut m = new_opacity_map(4, 4);
64        opacity_set(&mut m, 2, 2, 0.3);
65        assert!((opacity_get(&m, 2, 2) - 0.3).abs() < 1e-5);
66    }
67
68    #[test]
69    fn test_opacity_to_u8() {
70        /* converts to u8 range */
71        let m = new_opacity_map(2, 2);
72        let b = opacity_to_u8(&m);
73        assert_eq!(b.len(), 4);
74        assert_eq!(b[0], 255);
75    }
76
77    #[test]
78    fn test_opacity_mean() {
79        /* mean of all-1 map is 1 */
80        let m = new_opacity_map(3, 3);
81        assert!((opacity_mean(&m) - 1.0).abs() < 1e-5);
82    }
83
84    #[test]
85    fn test_opacity_threshold_mask() {
86        /* threshold at 0.5 on all-1 map */
87        let m = new_opacity_map(2, 2);
88        let mask = opacity_threshold_mask(&m, 0.5);
89        assert!(mask.iter().all(|&b| b));
90    }
91
92    #[test]
93    fn test_opacity_get_oob() {
94        /* out-of-bounds returns 0 */
95        let m = new_opacity_map(2, 2);
96        assert_eq!(opacity_get(&m, 99, 99), 0.0);
97    }
98}