use crate::Error;
use image::DynamicImage;
use ravif_new::*;
use rgb::FromSlice;
use crate::converter::DEPENDENCIES;
macro_rules! copy_enum_variants {
($name:ident, $($variant:ident),*) => {
#[allow(missing_docs)]
#[derive(clap::ValueEnum, Clone, Copy, PartialEq, Eq, Debug)]
pub enum $name {
$($variant),*
}
};
}
copy_enum_variants!(BitDepth, Eight, Ten, Auto);
copy_enum_variants!(ColorModel, YCbCr, RGB);
copy_enum_variants!(AlphaColorMode, UnassociatedDirty, UnassociatedClean, Premultiplied);
fn convert_bit_depth_to_ext(bit_depth: Option<BitDepth>) -> ravif_new::BitDepth {
match bit_depth.unwrap_or(BitDepth::Auto) {
BitDepth::Eight => ravif_new::BitDepth::Eight,
BitDepth::Ten => ravif_new::BitDepth::Ten,
BitDepth::Auto => ravif_new::BitDepth::Auto
}
}
fn convert_color_model_to_ext(color_model: Option<ColorModel>) -> ravif_new::ColorModel {
match color_model.unwrap_or(ColorModel::YCbCr) {
ColorModel::YCbCr => ravif_new::ColorModel::YCbCr,
ColorModel::RGB => ravif_new::ColorModel::RGB
}
}
fn convert_alpha_color_mode_to_ext(alpha_color_mode: Option<AlphaColorMode>) -> ravif_new::AlphaColorMode {
match alpha_color_mode.unwrap_or(AlphaColorMode::UnassociatedClean) {
AlphaColorMode::UnassociatedDirty => ravif_new::AlphaColorMode::UnassociatedDirty,
AlphaColorMode::UnassociatedClean => ravif_new::AlphaColorMode::UnassociatedClean,
AlphaColorMode::Premultiplied => ravif_new::AlphaColorMode::Premultiplied
}
}
pub fn encoder_info(quality: f32, speed: u8,
bit_depth: Option<BitDepth>, color_model: Option<ColorModel>) -> String {
let mut ravif_version = "";
match DEPENDENCIES.iter().rfind(|&&(name, _)| name == "ravif") {
Some((_name, version)) => {
ravif_version = version;
}
None => {
println!("Package '{}' not found", "ravif");
}
};
format!(
"Using \"ravif\" ({}) with options (quality: {}, speed: {}, bit depth: {:?}, color model: {:?})",
ravif_version,
quality,
speed,
convert_bit_depth_to_ext(bit_depth),
convert_color_model_to_ext(color_model)
)
}
pub fn encode_avif(image: &DynamicImage, quality: f32, speed: u8,
bit_depth: Option<BitDepth>, color_model: Option<ColorModel>,
alpha_color_mode: Option<AlphaColorMode>, alpha_quality: f32) -> Result<Vec<u8>, Error> {
let avif_res: EncodedImage;
if image.color().has_alpha() {
let source_image = image.to_rgba8();
let image = Img::new(source_image.as_rgba(), image.width() as usize, image.height() as usize);
avif_res = Encoder::new()
.with_quality(quality)
.with_speed(speed) .with_bit_depth(convert_bit_depth_to_ext(bit_depth))
.with_internal_color_model(convert_color_model_to_ext(color_model))
.with_alpha_quality(alpha_quality) .with_alpha_color_mode(convert_alpha_color_mode_to_ext(alpha_color_mode)) .encode_rgba(image)
.map_err(|e| Error::from_string(format!("avif encoding failed: {:?}", e)))?;
} else {
let source_image = image.to_rgb8();
let image = Img::new(source_image.as_rgb(), image.width() as usize, image.height() as usize);
avif_res = Encoder::new()
.with_quality(quality)
.with_speed(speed) .with_bit_depth(convert_bit_depth_to_ext(bit_depth))
.with_internal_color_model(convert_color_model_to_ext(color_model))
.encode_rgb(image)
.map_err(|e| Error::from_string(format!("avif encoding failed: {:?}", e)))?;
}
Ok(avif_res.avif_file)
}