aboutsummaryrefslogtreecommitdiff
path: root/transcoder/src/image.rs
blob: 29ad42317baf778c9f3c49a0bde26ec4fef7e9af (plain)
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
use jellybase::{cache_file, AssetLocationExt};
use jellycommon::AssetLocation;
use log::info;
use rgb::FromSlice;
use std::{
    fs::File,
    io::{BufReader, Write},
    path::PathBuf,
};

pub fn transcode(
    asset: AssetLocation,
    quality: f32,
    speed: u8,
    width: usize,
) -> anyhow::Result<PathBuf> {
    let original_path = asset.path();
    let path = cache_file(&[
        original_path.as_os_str().to_str().unwrap(),
        &format!("{width} {quality} {speed}"),
    ]);
    if !path.exists() {
        info!("encoding {path:?} (speed={speed}, quality={quality}, width={width})");
        let reader = image::io::Reader::new(BufReader::new(File::open(original_path)?))
            .with_guessed_format()?;
        let original = reader.decode()?.to_rgba8();
        let image = image::imageops::resize(
            &original,
            width as u32,
            width as u32 * original.height() / original.width(),
            image::imageops::FilterType::Lanczos3,
        );
        let pixels = image.to_vec();
        let encoded = ravif::Encoder::new()
            .with_speed(speed.clamp(1, 10))
            .with_quality(quality.clamp(1., 100.))
            .encode_rgba(ravif::Img::new(
                pixels.as_rgba(),
                image.width() as usize,
                image.height() as usize,
            ))?;
        info!("transcode finished");
        File::create(&path)?.write_all(&encoded.avif_file)?;
    }
    Ok(path)
}