opencv_core/
scalar.rs

1//! Scalar and vector types for OpenCV
2
3use std::fmt;
4use serde::{Serialize, Deserialize};
5
6/// 4-element scalar value used throughout OpenCV
7#[derive(Debug, Clone, Copy, PartialEq)]
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9pub struct Scalar {
10    pub val: [f64; 4],
11}
12
13impl Scalar {
14    /// Create a new scalar with all elements set to the same value
15    pub fn all(v: f64) -> Self {
16        Self { val: [v, v, v, v] }
17    }
18
19    /// Create a scalar from individual values
20    pub fn new(v0: f64, v1: f64, v2: f64, v3: f64) -> Self {
21        Self { val: [v0, v1, v2, v3] }
22    }
23
24    /// Create a scalar for grayscale (single channel)
25    pub fn gray(v: f64) -> Self {
26        Self::new(v, 0.0, 0.0, 0.0)
27    }
28
29    /// Create a scalar for RGB color
30    pub fn rgb(r: f64, g: f64, b: f64) -> Self {
31        Self::new(b, g, r, 0.0) // OpenCV uses BGR order
32    }
33
34    /// Create a scalar for RGBA color
35    pub fn rgba(r: f64, g: f64, b: f64, a: f64) -> Self {
36        Self::new(b, g, r, a) // OpenCV uses BGRA order
37    }
38
39    /// Get element at index
40    pub fn get(&self, index: usize) -> f64 {
41        if index < 4 {
42            self.val[index]
43        } else {
44            0.0
45        }
46    }
47
48    /// Set element at index
49    pub fn set(&mut self, index: usize, value: f64) {
50        if index < 4 {
51            self.val[index] = value;
52        }
53    }
54
55    /// Check if all elements are zero
56    pub fn is_zero(&self) -> bool {
57        self.val.iter().all(|&x| x == 0.0)
58    }
59
60    /// Get the magnitude (L2 norm) of the scalar
61    pub fn magnitude(&self) -> f64 {
62        (self.val[0] * self.val[0] + 
63         self.val[1] * self.val[1] + 
64         self.val[2] * self.val[2] + 
65         self.val[3] * self.val[3]).sqrt()
66    }
67}
68
69impl Default for Scalar {
70    fn default() -> Self {
71        Self { val: [0.0; 4] }
72    }
73}
74
75impl fmt::Display for Scalar {
76    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77        write!(f, "[{:.2}, {:.2}, {:.2}, {:.2}]", 
78               self.val[0], self.val[1], self.val[2], self.val[3])
79    }
80}
81
82impl From<f64> for Scalar {
83    fn from(v: f64) -> Self {
84        Self::all(v)
85    }
86}
87
88impl From<(f64, f64, f64)> for Scalar {
89    fn from((v0, v1, v2): (f64, f64, f64)) -> Self {
90        Self::new(v0, v1, v2, 0.0)
91    }
92}
93
94impl From<(f64, f64, f64, f64)> for Scalar {
95    fn from((v0, v1, v2, v3): (f64, f64, f64, f64)) -> Self {
96        Self::new(v0, v1, v2, v3)
97    }
98}
99
100impl From<[f64; 4]> for Scalar {
101    fn from(val: [f64; 4]) -> Self {
102        Self { val }
103    }
104}
105
106impl From<Scalar> for [f64; 4] {
107    fn from(scalar: Scalar) -> Self {
108        scalar.val
109    }
110}
111
112
113/// Generic N-dimensional vector
114#[derive(Debug, Clone, PartialEq)]
115pub struct VecN<T, const N: usize> {
116    pub val: [T; N],
117}
118
119impl<T: Copy + Default, const N: usize> VecN<T, N> {
120    /// Create a new vector with all elements set to default
121    pub fn new() -> Self {
122        Self { val: [T::default(); N] }
123    }
124
125    /// Create a vector from an array
126    pub fn from_array(val: [T; N]) -> Self {
127        Self { val }
128    }
129
130    /// Get element at index
131    pub fn get(&self, index: usize) -> Option<&T> {
132        self.val.get(index)
133    }
134
135    /// Set element at index
136    pub fn set(&mut self, index: usize, value: T) -> bool {
137        if index < N {
138            self.val[index] = value;
139            true
140        } else {
141            false
142        }
143    }
144
145    /// Get the length of the vector
146    pub fn len(&self) -> usize {
147        N
148    }
149
150    /// Check if vector is empty (should never be true for const generic)
151    pub fn is_empty(&self) -> bool {
152        N == 0
153    }
154}
155
156impl<T: Copy + Default, const N: usize> Default for VecN<T, N> {
157    fn default() -> Self {
158        Self::new()
159    }
160}
161
162impl<T: fmt::Display, const N: usize> fmt::Display for VecN<T, N> {
163    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164        write!(f, "[")?;
165        for (i, val) in self.val.iter().enumerate() {
166            if i > 0 {
167                write!(f, ", ")?;
168            }
169            write!(f, "{}", val)?;
170        }
171        write!(f, "]")
172    }
173}
174
175/// Common vector type aliases
176pub type Vec2b = VecN<u8, 2>;
177pub type Vec3b = VecN<u8, 3>;
178pub type Vec4b = VecN<u8, 4>;
179pub type Vec2s = VecN<i16, 2>;
180pub type Vec3s = VecN<i16, 3>;
181pub type Vec4s = VecN<i16, 4>;
182pub type Vec2w = VecN<u16, 2>;
183pub type Vec3w = VecN<u16, 3>;
184pub type Vec4w = VecN<u16, 4>;
185pub type Vec2i = VecN<i32, 2>;
186pub type Vec3i = VecN<i32, 3>;
187pub type Vec4i = VecN<i32, 4>;
188pub type Vec2f = VecN<f32, 2>;
189pub type Vec3f = VecN<f32, 3>;
190pub type Vec4f = VecN<f32, 4>;
191pub type Vec2d = VecN<f64, 2>;
192pub type Vec3d = VecN<f64, 3>;
193pub type Vec4d = VecN<f64, 4>;
194
195#[cfg(test)]
196mod tests {
197    use super::*;
198
199    #[test]
200    fn test_scalar_creation() {
201        let s1 = Scalar::all(10.0);
202        assert_eq!(s1.val, [10.0, 10.0, 10.0, 10.0]);
203
204        let s2 = Scalar::new(1.0, 2.0, 3.0, 4.0);
205        assert_eq!(s2.val, [1.0, 2.0, 3.0, 4.0]);
206
207        let s3 = Scalar::gray(128.0);
208        assert_eq!(s3.val, [128.0, 0.0, 0.0, 0.0]);
209
210        let s4 = Scalar::rgb(255.0, 128.0, 64.0);
211        assert_eq!(s4.val, [64.0, 128.0, 255.0, 0.0]); // BGR order
212    }
213
214    #[test]
215    fn test_scalar_operations() {
216        let mut s = Scalar::new(1.0, 2.0, 3.0, 4.0);
217        
218        assert_eq!(s.get(0), 1.0);
219        assert_eq!(s.get(2), 3.0);
220        assert_eq!(s.get(5), 0.0); // Out of bounds
221
222        s.set(1, 10.0);
223        assert_eq!(s.get(1), 10.0);
224
225        let magnitude = s.magnitude();
226        assert!((magnitude - (1.0 + 100.0 + 9.0 + 16.0_f64).sqrt()).abs() < 1e-10);
227    }
228
229    #[test]
230    fn test_scalar_conversions() {
231        let s1: Scalar = 5.0.into();
232        assert_eq!(s1.val, [5.0, 5.0, 5.0, 5.0]);
233
234        let s2: Scalar = (1.0, 2.0, 3.0).into();
235        assert_eq!(s2.val, [1.0, 2.0, 3.0, 0.0]);
236
237        let s3: Scalar = (1.0, 2.0, 3.0, 4.0).into();
238        assert_eq!(s3.val, [1.0, 2.0, 3.0, 4.0]);
239
240        let arr: [f64; 4] = s3.into();
241        assert_eq!(arr, [1.0, 2.0, 3.0, 4.0]);
242    }
243
244    #[test]
245    fn test_vecn() {
246        let mut v = Vec3f::new();
247        assert_eq!(v.len(), 3);
248        
249        v.set(0, 1.0);
250        v.set(1, 2.0);
251        v.set(2, 3.0);
252        
253        assert_eq!(v.get(0), Some(&1.0));
254        assert_eq!(v.get(1), Some(&2.0));
255        assert_eq!(v.get(2), Some(&3.0));
256        assert_eq!(v.get(3), None);
257
258        let v2 = Vec3f::from_array([4.0, 5.0, 6.0]);
259        assert_eq!(v2.val, [4.0, 5.0, 6.0]);
260    }
261
262    #[test]
263    fn test_scalar_zero() {
264        let zero = Scalar::default();
265        assert!(zero.is_zero());
266
267        let non_zero = Scalar::new(1.0, 0.0, 0.0, 0.0);
268        assert!(!non_zero.is_zero());
269    }
270}