2121//! The type used must match the bit depth specified when creating frames:
2222//! - 8-bit frames must use `u8`
2323//! - 9-16 bit frames must use `u16`
24+ //!
25+ //! # Working with `T: Pixel`
26+ //!
27+ //! It is often necessary to convert between an abstract pixel and their concrete
28+ //! integer representation in order to work with them, for example to implement an
29+ //! algorithm operating on video frames.
30+ //!
31+ //! For this purpose, `Pixel` is a supertrait of some conversions from the standard
32+ //! library, namely:
33+ //! - `Into<u16>` to convert any pixel into a `u16`,
34+ //! - `TryInto<u8>` to try to convert any pixel into a `u8` (not possible if `T` is larger
35+ //! than one byte),
36+ //! - `From<u8>` to convert any `u8` into a Pixel containing the given value and
37+ //! - `TryFrom<u16>` to try to convert any `u16` into a `T` (not possible if `T` is smaller
38+ //! than two bytes).
39+ //!
40+ //! For example, to sum all pixels in a row:
41+ //!
42+ //! ```
43+ //! use v_frame::frame::Frame;
44+ //! use v_frame::pixel::Pixel;
45+ //!
46+ //! pub fn summed_rows<T: Pixel>(frame: &Frame<T>) -> Vec<u64> {
47+ //! frame.y_plane
48+ //! .rows()
49+ //! // row is &[T] here
50+ //! .map(|row| {
51+ //! row.iter()
52+ //! .map(|&pix| pix.into()) // convert T -> u16
53+ //! .map(|pix| u64::from(pix)) // widen so sum doesn't overflow
54+ //! .sum()
55+ //! })
56+ //! .collect()
57+ //! }
58+ //! ```
59+ //!
60+ //! Note that Pixel only provides one `Into<T>` implementation so it is not necessary to
61+ //! explicitly specify the wanted type (`<T as Into<u16>>::into(pix)`).
62+ //!
63+ //! Here's a somewhat contrived example of how to convert integers into pixels:
64+ //!
65+ //! ```
66+ //! use v_frame::frame::Frame;
67+ //! use v_frame::pixel::Pixel;
68+ //!
69+ //! fn random_value() -> i32 {
70+ //! // chosen by a fair dice roll
71+ //! 4
72+ //! }
73+ //!
74+ //! fn clamp_to_range(value: i32, bit_depth: u8) -> u16 {
75+ //! let bit_depth_max = (1u16 << bit_depth) - 1;
76+ //!
77+ //! if value < 0 {
78+ //! 0
79+ //! } else if value > i32::from(bit_depth_max) {
80+ //! bit_depth_max
81+ //! } else {
82+ //! value as u16
83+ //! }
84+ //! }
85+ //!
86+ //! pub fn change_some_rows<T: Pixel>(frame: &mut Frame<T>, bit_depth: u8) {
87+ //! for pix in frame.y_plane.pixels_mut() {
88+ //! let old_val = i32::from((*pix).into());
89+ //!
90+ //! let new_val = clamp_to_range(old_val + random_value(), bit_depth);
91+ //! if size_of::<T>() == 1 {
92+ //! *pix = T::from(new_val as u8)
93+ //! } else {
94+ //! *pix = T::try_from(new_val).expect("T is u16");
95+ //! }
96+ //! }
97+ //! }
98+ //! ```
99+ //!
100+ //! Again, `From<u8>` and `TryFrom<u16>` are the only implementations for the respective traits
101+ //! so it's not necessary to specify which one is being used.
24102
25103use core:: fmt:: { Binary , Debug , Display , LowerExp , LowerHex , Octal , UpperExp , UpperHex } ;
26104use core:: hash:: Hash ;
@@ -41,6 +119,8 @@ mod private {
41119/// data structures and algorithms to work with both standard and high bit-depth
42120/// video content.
43121///
122+ /// See the [module documentation][crate::pixel] for more details.
123+ ///
44124/// # Type Safety
45125///
46126/// The library enforces correct type usage through validation:
0 commit comments