1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
use crate::{AddImageFlags, AvifData, AvifImage, Error};
use libavif_sys as sys;
/// AVIF image encoder
///
/// ## Encoding a single image
///
/// ```no_run
/// # use std::fs;
/// # use libavif::{AvifImage, Encoder};
/// #
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let luma_data = fs::read("luma.raw")?;
/// let image = AvifImage::from_luma8(128, 128, &luma_data)?;
/// let encoder = Encoder::new();
/// let data = encoder.encode(&image)?;
/// fs::write("luma.avif", &*data)?;
/// # Ok(())
/// # }
/// ```
///
/// ## Encoding an image sequence
///
/// ```no_run
/// # use std::fs;
/// # use libavif::{AvifImage, Encoder};
/// #
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let mut encoder = Encoder::new();
/// // Set timescale to 60Hz...
/// encoder.set_timescale(60);
/// for i in 0..60 {
/// let luma_data = fs::read(&format!("luma{}.raw", i))?;
/// let image = AvifImage::from_luma8(128, 128, &luma_data)?;
/// // ...so we can use 1 as the duration.
/// // The duration of a single frame is now 1/60 s.
/// // So the framerate is 60fps
/// encoder.add_image(&image, 1, Default::default())?;
/// }
/// let data = encoder.finish()?;
/// fs::write("luma_animation.avif", &*data)?;
/// # Ok(())
/// # }
/// ```
pub struct Encoder {
encoder: *mut sys::avifEncoder,
}
impl Encoder {
/// Create a new encoder with default settings
///
/// # Defaults
///
/// * `max_threads` -> `1`
/// * `quantizer` -> `0`
/// * `quantizer_alpha` -> `0`
/// * `speed` -> `10`
pub fn new() -> Self {
let encoder = unsafe { sys::avifEncoderCreate() };
Self { encoder }
}
/// Get the maximum allowed number of threads this `Encoder` can use
pub fn max_threads(&self) -> usize {
unsafe { (*self.encoder).maxThreads as usize }
}
/// Set the maximum allowed number of threads this `Encoder` can use
pub fn set_max_threads(&mut self, max_threads: usize) -> &mut Self {
unsafe { (*self.encoder).maxThreads = max_threads.max(1) as i32 }
self
}
/// Get quality of the YUV channels
pub fn quality(&self) -> u8 {
unsafe { (*self.encoder).quality as u8 }
}
/// Set the quality for the YUV channels
///
/// Must be between 0 and 100.
///
/// * `100` - _lossless quality_
/// * `0` - _lowest quality_
pub fn set_quality(&mut self, quality: u8) -> &mut Self {
let quality = quality.min(100);
unsafe {
(*self.encoder).quality = quality.into();
}
self
}
/// Get quality of the alpha channel
pub fn alpha_quality(&self) -> u8 {
unsafe { (*self.encoder).qualityAlpha as u8 }
}
/// Set the quality for the alpha channel
///
/// Must be between 0 and 100.
///
/// * `100` - _lossless quality_
/// * `0` - _lowest quality_
pub fn set_alpha_quality(&mut self, alpha_quality: u8) -> &mut Self {
let alpha_quality = alpha_quality.min(100);
unsafe {
(*self.encoder).qualityAlpha = alpha_quality.into();
}
self
}
/// Get the speed of this `Encoder`
pub fn speed(&self) -> u8 {
unsafe { (*self.encoder).speed as u8 }
}
/// Set the speed of this `Encoder`
///
/// Must be between 0 and 10.
///
/// * `10` - _fastest_
/// * `0` - _slowest_
pub fn set_speed(&mut self, speed: u8) -> &mut Self {
unsafe { (*self.encoder).speed = speed.min(10) as i32 }
self
}
/// Get the timescale of this `Encoder` in Hz (1/s)
pub fn timescale(&self) -> u64 {
unsafe { (*self.encoder).timescale }
}
/// Set the timescale of this `Encoder` in Hz (1/s)
///
/// The duration of an image in seconds is `duration_in_timescales / timescale [s]`.
///
/// For example, an image with a duration of `1` added to an `Encoder` with a timescale of `60 Hz`
/// would mean the image has a duration of `1/60 s`.
pub fn set_timescale(&mut self, timescale: u64) -> &mut Self {
unsafe { (*self.encoder).timescale = timescale }
self
}
/// Encode an `AvifImage` using the settings from this `Encoder`
///
/// Calling this function is the same as calling [`add_image`](Self::add_image) with
/// [`AddImageFlags::SINGLE`](crate::AddImageFlags::SINGLE) and calling [`finish`](Self::finish).
pub fn encode(&self, image: &AvifImage) -> Result<AvifData<'static>, Error> {
let mut data = Default::default();
unsafe {
Error::code(sys::avifEncoderWrite(
self.encoder,
image.inner(),
&mut data,
))?;
Ok(AvifData::from_raw(data))
}
}
/// Add an `AvifImage` to this `Encoder`.
pub fn add_image(
&self,
image: &AvifImage,
duration_in_timescales: u64,
flags: AddImageFlags,
) -> Result<(), super::Error> {
unsafe {
Error::code(sys::avifEncoderAddImage(
self.encoder,
image.inner(),
duration_in_timescales,
flags.into(),
))
}
}
/// Finish encoding an image or an animation.
///
/// You only need to call this function if you used [`add_image`](Self::add_image).
pub fn finish(&self) -> Result<AvifData<'static>, super::Error> {
unsafe {
let mut data = Default::default();
Error::code(sys::avifEncoderFinish(self.encoder, &mut data))?;
Ok(AvifData::from_raw(data))
}
}
}
impl Drop for Encoder {
fn drop(&mut self) {
unsafe {
sys::avifEncoderDestroy(self.encoder);
}
}
}
impl Default for Encoder {
fn default() -> Self {
Self::new()
}
}