afi/
video.rs

1// "afi" - Aldaron's Format Interface
2//
3// Copyright Jeron A. Lau 2017-2018.
4// Distributed under the Boost Software License, Version 1.0.  (See accompanying
5// file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
6
7use VFrame;
8use std::collections::VecDeque;
9use std::mem::transmute;
10
11/// The format for the color channels of the `Video`.
12#[derive(Copy, Clone, PartialEq)] #[repr(u8)]
13pub enum ColorChannels {
14	/// Grayscale color format, 1 channel (stored in red channel).
15	Grayscale = 1u8,
16	/// RGB color format, 3 channels.
17	Rgb = 3u8,
18	/// RGBA color format, 4 channels.
19	Rgba = 4u8,
20	/// BGR color format, 3 channels.
21	Bgr = 8u8,
22	/// BGRA color format, 4 channels.
23	Bgra = 9u8,
24	/// YCbCr color format, 3 channels
25	YCbCr = 13u8,
26}
27
28impl Default for ColorChannels {
29	fn default() -> ColorChannels { Rgba }
30}
31
32pub use ColorChannels::*;
33
34impl ColorChannels {
35	/// Convert a pixel to this format from another.
36	pub fn from(self, from: ColorChannels, p: [u8; 4]) -> [u8; 4] {
37		if self == from {
38			p
39		} else {
40			self.rgba_to(from.to_rgba(p))
41		}
42	}
43
44	/// Pack an RGBA [u8; 4] into an RGBA u32
45	pub fn pack(p: [u8; 4]) -> u32 {
46		let r = (p[0] as u32).rotate_right(0); 
47		let g = (p[1] as u32).rotate_right(8);
48		let b = (p[2] as u32).rotate_right(16);
49		let a = (p[3] as u32).rotate_right(24);
50
51		r | g | b | a
52	}
53
54	/// Unpack an RGBA u32 into an RGBA [u8; 4]
55	pub fn unpack(p: u32) -> [u8; 4] {
56		unsafe {
57			transmute(p)
58		}
59	}
60
61	/// Convert a pixel from RGBA to this format.
62	fn rgba_to(self, p: [u8; 4]) -> [u8; 4] {
63		let [r, g, b, a] = p;
64		match self {
65			Grayscale => {
66				let gray = (r as u16 + g as u16 + b as u16) / 3;
67				[gray as u8, 255, 255, 255]
68			},
69			Rgb => [r, g, b, 255],
70			Rgba => [r, g, b, a],
71			Bgr => [b, g, r, 255],
72			Bgra => [b, g, r, a],
73			// From https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion
74			YCbCr => {
75				let [r, g, b] = [r as f64, g as f64, b as f64];
76				let y = (0.299 * r) + (0.587 * g) + (0.114 * b);
77				let cb = 128.0 - (0.168736 * r) - (0.331264 * g)
78					+ (0.5  * b);
79				let cr = 128.0 + (0.5 * r) - (0.418688 * g)
80					- (0.081312 * b);
81				[y as u8, cb as u8, cr as u8, 255]
82			}
83		}
84	}
85
86	/// Convert a pixel in this format to RGBA.
87	fn to_rgba(self, p: [u8; 4]) -> [u8; 4] {
88		let [r, g, b, a] = p;
89		match self {
90			Grayscale => [r, r, r, r],
91			Rgb => [r, g, b, 255],
92			Rgba => [r, g, b, a],
93			Bgr => [b, g, r, 255],
94			Bgra => [b, g, r, a],
95			// From https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion
96			YCbCr => {
97				let [y, cb, cr] = [r as f64, g as f64, b as f64];
98				let r = y + 1.402 * (cr - 128.0);
99				let g = y - 0.344136 * (cb - 128.0) - 0.714136 *
100					(cr - 128.0);
101				let b = y + 1.772 * (cb - 128.0);
102				[r as u8, g as u8, b as u8, 255]
103			}
104		}
105	}
106
107	/// Return the number of channels.
108	pub fn n_channels(self) -> usize {
109		(self as u8 % 5) as usize
110	}
111}
112
113/// A Video Buffer (24fps).
114pub struct Video {
115	format: ColorChannels,
116	wh: (u16, u16),
117	n_frames: u32, // number of frames in the whole video.
118	frames: VecDeque<VFrame>,
119}
120
121impl Video {
122	/// Create a new video buffer.
123	pub fn new(format: ColorChannels, wh: (u16, u16), n_frames: u32) -> Self
124	{
125		Video {
126			wh, n_frames, format, frames: VecDeque::new(),
127		}
128	}
129
130	/// Get the width and height of the video.
131	pub fn wh(&self) -> (u16, u16) {
132		self.wh
133	}
134
135	/// Get the video buffer's color format.
136	pub fn format(&self) -> ColorChannels {
137		self.format
138	}
139
140	/// Add frame to the buffer.
141	pub fn add(&mut self, data: VFrame) {
142		self.frames.push_back(data);
143	}
144
145	/// Return the number frames in the buffer.
146	pub fn len(&self) -> u32 {
147		self.frames.len() as u32
148	}
149
150	/// Returns pixels for the next frame on the Queue.
151	pub fn pop(&mut self) -> Option<VFrame> {
152		Some(self.frames.pop_front()?)
153	}
154
155	/// Return the number of channels.
156	pub fn n_channels(&self) -> usize {
157		self.format.n_channels()
158	}
159
160	/// Return the total number of frames in the video.
161	pub fn frames(&self) -> u32 {
162		self.n_frames
163	}
164}