use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Resolution {
pub width: u32,
pub height: u32,
}
impl Resolution {
pub fn new(w: u32, h: u32) -> Self {
Self {
width: w,
height: h,
}
}
pub fn p360() -> Self {
Self::new(640, 360)
}
pub fn p480() -> Self {
Self::new(854, 480)
}
pub fn p720() -> Self {
Self::new(1280, 720)
}
pub fn p1080() -> Self {
Self::new(1920, 1080)
}
pub fn p1440() -> Self {
Self::new(2560, 1440)
}
pub fn p4k() -> Self {
Self::new(3840, 2160)
}
pub fn aspect_ratio(&self) -> (u32, u32) {
let g = gcd(self.width, self.height);
match (self.width.checked_div(g), self.height.checked_div(g)) {
(Some(w), Some(h)) => (w, h),
_ => (0, 0),
}
}
pub fn aspect_ratio_f64(&self) -> f64 {
if self.height == 0 {
0.0
} else {
self.width as f64 / self.height as f64
}
}
pub fn is_portrait(&self) -> bool {
self.height > self.width
}
pub fn is_landscape(&self) -> bool {
self.width > self.height
}
pub fn is_square(&self) -> bool {
self.width == self.height
}
pub fn pixel_count(&self) -> u64 {
self.width as u64 * self.height as u64
}
pub fn scale_to_fit(&self, max_width: u32, max_height: u32) -> Self {
let w_ratio = max_width as f64 / self.width as f64;
let h_ratio = max_height as f64 / self.height as f64;
let ratio = w_ratio.min(h_ratio);
Self::new(
(self.width as f64 * ratio).round() as u32,
(self.height as f64 * ratio).round() as u32,
)
}
pub fn scale_to_fill(&self, width: u32, height: u32) -> Self {
let w_ratio = width as f64 / self.width as f64;
let h_ratio = height as f64 / self.height as f64;
let ratio = w_ratio.max(h_ratio);
Self::new(
(self.width as f64 * ratio).round() as u32,
(self.height as f64 * ratio).round() as u32,
)
}
pub fn scale_by(&self, factor: f64) -> Self {
Self::new(
(self.width as f64 * factor).round() as u32,
(self.height as f64 * factor).round() as u32,
)
}
}
fn gcd(a: u32, b: u32) -> u32 {
if b == 0 { a } else { gcd(b, a % b) }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct FrameRate {
pub num: u32,
pub den: u32,
}
impl FrameRate {
pub fn new(num: u32, den: u32) -> Self {
Self { num, den }
}
pub fn fps(n: u32) -> Self {
Self::new(n, 1)
}
pub fn fps_24() -> Self {
Self::new(24, 1)
}
pub fn fps_25() -> Self {
Self::new(25, 1)
}
pub fn fps_30() -> Self {
Self::new(30, 1)
}
pub fn fps_50() -> Self {
Self::new(50, 1)
}
pub fn fps_60() -> Self {
Self::new(60, 1)
}
pub fn ntsc_30() -> Self {
Self::new(30000, 1001)
}
pub fn ntsc_24() -> Self {
Self::new(24000, 1001)
}
pub fn ntsc_60() -> Self {
Self::new(60000, 1001)
}
pub fn as_f64(&self) -> f64 {
if self.den == 0 {
0.0
} else {
self.num as f64 / self.den as f64
}
}
}