opencv_core/
size.rs

1//! Size structures for OpenCV
2
3use std::fmt;
4use serde::{Serialize, Deserialize};
5
6/// 2D size with integer dimensions
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9pub struct Size {
10    pub width: i32,
11    pub height: i32,
12}
13
14impl Size {
15    /// Create a new size
16    pub fn new(width: i32, height: i32) -> Self {
17        Self { width, height }
18    }
19
20    /// Create a square size
21    pub fn square(size: i32) -> Self {
22        Self::new(size, size)
23    }
24
25    /// Calculate area
26    pub fn area(&self) -> i32 {
27        self.width * self.height
28    }
29
30    /// Check if size is empty (width or height <= 0)
31    pub fn is_empty(&self) -> bool {
32        self.width <= 0 || self.height <= 0
33    }
34
35    /// Get aspect ratio (width/height)
36    pub fn aspect_ratio(&self) -> f64 {
37        if self.height != 0 {
38            self.width as f64 / self.height as f64
39        } else {
40            0.0
41        }
42    }
43}
44
45impl Default for Size {
46    fn default() -> Self {
47        Self::new(0, 0)
48    }
49}
50
51impl fmt::Display for Size {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        write!(f, "{}x{}", self.width, self.height)
54    }
55}
56
57impl From<(i32, i32)> for Size {
58    fn from((width, height): (i32, i32)) -> Self {
59        Self::new(width, height)
60    }
61}
62
63impl From<Size> for (i32, i32) {
64    fn from(size: Size) -> Self {
65        (size.width, size.height)
66    }
67}
68
69/// 2D size with single-precision floating-point dimensions
70#[derive(Debug, Clone, Copy, PartialEq)]
71#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
72pub struct Size2f {
73    pub width: f32,
74    pub height: f32,
75}
76
77impl Size2f {
78    /// Create a new size
79    pub fn new(width: f32, height: f32) -> Self {
80        Self { width, height }
81    }
82
83    /// Create a square size
84    pub fn square(size: f32) -> Self {
85        Self::new(size, size)
86    }
87
88    /// Calculate area
89    pub fn area(&self) -> f32 {
90        self.width * self.height
91    }
92
93    /// Check if size is empty (width or height <= 0)
94    pub fn is_empty(&self) -> bool {
95        self.width <= 0.0 || self.height <= 0.0
96    }
97
98    /// Get aspect ratio (width/height)
99    pub fn aspect_ratio(&self) -> f32 {
100        if self.height != 0.0 {
101            self.width / self.height
102        } else {
103            0.0
104        }
105    }
106}
107
108impl Default for Size2f {
109    fn default() -> Self {
110        Self::new(0.0, 0.0)
111    }
112}
113
114impl fmt::Display for Size2f {
115    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116        write!(f, "{:.2}x{:.2}", self.width, self.height)
117    }
118}
119
120impl From<(f32, f32)> for Size2f {
121    fn from((width, height): (f32, f32)) -> Self {
122        Self::new(width, height)
123    }
124}
125
126impl From<Size2f> for (f32, f32) {
127    fn from(size: Size2f) -> Self {
128        (size.width, size.height)
129    }
130}
131
132impl From<Size> for Size2f {
133    fn from(size: Size) -> Self {
134        Self::new(size.width as f32, size.height as f32)
135    }
136}
137
138/// 2D size with double-precision floating-point dimensions
139#[derive(Debug, Clone, Copy, PartialEq)]
140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
141pub struct Size2d {
142    pub width: f64,
143    pub height: f64,
144}
145
146impl Size2d {
147    /// Create a new size
148    pub fn new(width: f64, height: f64) -> Self {
149        Self { width, height }
150    }
151
152    /// Create a square size
153    pub fn square(size: f64) -> Self {
154        Self::new(size, size)
155    }
156
157    /// Calculate area
158    pub fn area(&self) -> f64 {
159        self.width * self.height
160    }
161
162    /// Check if size is empty (width or height <= 0)
163    pub fn is_empty(&self) -> bool {
164        self.width <= 0.0 || self.height <= 0.0
165    }
166
167    /// Get aspect ratio (width/height)
168    pub fn aspect_ratio(&self) -> f64 {
169        if self.height != 0.0 {
170            self.width / self.height
171        } else {
172            0.0
173        }
174    }
175}
176
177impl Default for Size2d {
178    fn default() -> Self {
179        Self::new(0.0, 0.0)
180    }
181}
182
183impl fmt::Display for Size2d {
184    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185        write!(f, "{:.6}x{:.6}", self.width, self.height)
186    }
187}
188
189impl From<(f64, f64)> for Size2d {
190    fn from((width, height): (f64, f64)) -> Self {
191        Self::new(width, height)
192    }
193}
194
195impl From<Size2d> for (f64, f64) {
196    fn from(size: Size2d) -> Self {
197        (size.width, size.height)
198    }
199}
200
201impl From<Size2f> for Size2d {
202    fn from(size: Size2f) -> Self {
203        Self::new(size.width as f64, size.height as f64)
204    }
205}
206
207#[cfg(test)]
208mod tests {
209    use super::*;
210
211    #[test]
212    fn test_size_creation() {
213        let size = Size::new(640, 480);
214        assert_eq!(size.width, 640);
215        assert_eq!(size.height, 480);
216        assert_eq!(size.area(), 307200);
217    }
218
219    #[test]
220    fn test_size_square() {
221        let size = Size::square(100);
222        assert_eq!(size.width, 100);
223        assert_eq!(size.height, 100);
224        assert_eq!(size.area(), 10000);
225    }
226
227    #[test]
228    fn test_size_aspect_ratio() {
229        let size = Size::new(16, 9);
230        assert!((size.aspect_ratio() - 16.0/9.0).abs() < 1e-10);
231    }
232
233    #[test]
234    fn test_size_empty() {
235        let empty_size = Size::new(0, 0);
236        assert!(empty_size.is_empty());
237        
238        let valid_size = Size::new(10, 10);
239        assert!(!valid_size.is_empty());
240    }
241
242    #[test]
243    fn test_size_conversions() {
244        let size = Size::new(100, 200);
245        let tuple: (i32, i32) = size.into();
246        assert_eq!(tuple, (100, 200));
247        
248        let size2: Size = (300, 400).into();
249        assert_eq!(size2.width, 300);
250        assert_eq!(size2.height, 400);
251    }
252}