Skip to content

Commit 6b267d5

Browse files
committed
doc: add explanation of how to use Pixel now
1 parent 4565425 commit 6b267d5

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

src/pixel.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,84 @@
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
25103
use core::fmt::{Binary, Debug, Display, LowerExp, LowerHex, Octal, UpperExp, UpperHex};
26104
use 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

Comments
 (0)