crypsol_storage 0.2.0

Multi-cloud storage library for Rust with image processing, validation, and thumbnail generation. Supports AWS S3, GCS, Azure Blob, Cloudflare R2, MinIO, and local filesystem.
Documentation
use std::io::Cursor;

use image::imageops::FilterType;
use image::{DynamicImage, ImageFormat, ImageReader, Limits};

use crate::error::Error;

/// Loads and validates an image from bytes with decompression limits.
pub fn load_image(data: &[u8], max_alloc: u64, max_dimension: u32) -> Result<DynamicImage, Error> {
    let mut reader = ImageReader::new(Cursor::new(data))
        .with_guessed_format()
        .map_err(|e| Error::ImageProcessing(format!("Failed to guess image format: {e}")))?;

    let mut limits = Limits::default();
    limits.max_alloc = Some(max_alloc);
    limits.max_image_width = Some(max_dimension);
    limits.max_image_height = Some(max_dimension);
    reader.limits(limits);

    reader
        .decode()
        .map_err(|e| Error::ImageProcessing(format!("Failed to decode image: {e}")))
}

/// Resizes an image to the specified dimensions.
pub fn resize_image(
    img: &DynamicImage,
    width: u32,
    height: u32,
    maintain_aspect: bool,
) -> DynamicImage {
    if maintain_aspect {
        img.resize(width, height, FilterType::Lanczos3)
    } else {
        img.resize_exact(width, height, FilterType::Lanczos3)
    }
}

/// Encodes an image to the specified format and returns bytes.
pub fn encode_image(img: &DynamicImage, format: ImageFormat) -> Result<Vec<u8>, Error> {
    let mut buffer = Vec::new();
    let mut cursor = Cursor::new(&mut buffer);
    img.write_to(&mut cursor, format)
        .map_err(|e| Error::ImageProcessing(format!("Failed to encode image: {e}")))?;
    Ok(buffer)
}

/// Determines the `ImageFormat` from a MIME content type.
pub fn format_from_content_type(content_type: &str) -> ImageFormat {
    match content_type {
        "image/png" => ImageFormat::Png,
        "image/gif" => ImageFormat::Gif,
        "image/webp" => ImageFormat::WebP,
        _ => ImageFormat::Jpeg,
    }
}

/// Returns the file extension for a MIME content type.
pub fn extension_from_content_type(content_type: &str) -> &str {
    match content_type {
        "image/png" => "png",
        "image/gif" => "gif",
        "image/webp" => "webp",
        _ => "jpg",
    }
}