silence_core/avif/encoding.rs
1//! Provides AV1 encoding for higher data efficiency via [`ravif`].
2
3use image::GenericImageView;
4use ravif::{EncodedImage, Encoder, Img};
5
6///
7/// Encodes a **formatted** image with the AV1 format.
8///
9/// **If you are looking to encode a [`crate::cam::Webcam::get_frame`]'s returned frame [`encode_raw_image`] is the one to use.**
10///
11/// # Behavior
12/// The **formatted** image is re-encoded with the settings the user passes in with the [`Encoder`] argument.
13/// The encoded image ([`ravif::EncodedImage`]) is returned from the image.
14///
15/// # Error
16/// Will return an error if the image format could not be guessed correctly or if the image had incorrect proerties (Eg.: Invalid size).
17///
18pub fn encode_image(encoder: Encoder, image: &[u8]) -> anyhow::Result<EncodedImage> {
19 //Parse image from bytes
20 let parsed_image = image::load_from_memory(image)?;
21
22 //Iter over the pixels
23 let colors = parsed_image
24 .pixels()
25 .map(|(_, _, color)| ravif::RGB8::new(color.0[0], color.0[1], color.0[2]))
26 .collect::<Vec<ravif::RGB8>>();
27
28 //Encode image
29 let encoded_image: EncodedImage = encoder.encode_rgb(Img::new(
30 colors.as_slice(),
31 parsed_image.width() as usize,
32 parsed_image.height() as usize,
33 ))?;
34
35 Ok(encoded_image)
36}
37
38///
39/// Encodes a raw image with the AV1 format
40///
41/// # Behavior
42/// The image is encoded with the settings the user passes in with the [`Encoder`] argument.
43/// The encoded image ([`EncodedImage`]) is returned from the raw image.
44///
45/// # Error
46/// If the image had incorrect proerties (Eg.: Invalid size).
47///
48pub fn encode_raw_image(
49 encoder: Encoder,
50 image: &[u8],
51 width: usize,
52 height: usize,
53) -> anyhow::Result<EncodedImage> {
54 //Iter over the raw pixels
55 let colors = image
56 .chunks_exact(3)
57 .map(|chunk| ravif::RGB8::new(chunk[0], chunk[1], chunk[2]))
58 .collect::<Vec<ravif::RGB8>>();
59
60 //Encode image
61 let encoded_image: EncodedImage =
62 encoder.encode_rgb(Img::new(colors.as_slice(), width, height))?;
63
64 Ok(encoded_image)
65}