Skip to main content

fotos_lib/ai/
compress.rs

1/// Image compression utility for LLM API submission.
2///
3/// Resizes images that exceed a maximum dimension and encodes as JPEG
4/// to reduce API costs and stay within provider size limits.
5use anyhow::Result;
6use base64::{engine::general_purpose::STANDARD, Engine};
7use image::DynamicImage;
8
9/// Resize and JPEG-encode an image for LLM submission.
10///
11/// If the image's longest side exceeds `max_dim`, it is resized proportionally.
12/// The result is JPEG-encoded at `quality` (1–100) and base64-encoded.
13pub fn compress_for_llm(image: &DynamicImage, max_dim: u32, quality: u8) -> Result<String> {
14    let (w, h) = (image.width(), image.height());
15
16    let resized = if w > max_dim || h > max_dim {
17        let scale = max_dim as f32 / w.max(h) as f32;
18        let new_w = ((w as f32 * scale).round() as u32).max(1);
19        let new_h = ((h as f32 * scale).round() as u32).max(1);
20        image.resize_exact(new_w, new_h, image::imageops::FilterType::Lanczos3)
21    } else {
22        image.clone()
23    };
24
25    let rgb = resized.to_rgb8();
26    let mut buf = Vec::new();
27    let mut encoder = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut buf, quality);
28    encoder.encode(
29        rgb.as_raw(),
30        rgb.width(),
31        rgb.height(),
32        image::ExtendedColorType::Rgb8,
33    )?;
34
35    Ok(STANDARD.encode(&buf))
36}