Procesamiento de imágenes en Rust: resize y crop
Rust es un lenguaje de programación de sistemas moderno que se utiliza cada vez más para tareas que requieren alto rendimiento y fiabilidad. El procesamiento de imágenes no es una excepción. En este artículo, veremos dos operaciones clave: cambiar el tamaño (resize) y recortar (crop) utilizando el ecosistema de Rust. Las bibliotecas principales: image (carga, guardado, manipulaciones básicas) y imageproc (procesamiento avanzado).
¿Por qué Rust para trabajar con imágenes?
Rust ofrece:
- Gestión segura de la memoria — sin fugas ni condiciones de carrera.
- Máximo rendimiento — comparable a C/C++.
- Ecosistema rico — el crate
imageadmite JPEG, PNG, GIF, BMP, WEBP y otros formatos. - Paralelismo — fácil de escalar el procesamiento en procesadores multinúcleo.
Instalación de dependencias
Añada a Cargo.toml:
[dependencies]image = "0.25"imageproc = "0.25" # para filtros avanzados (opcional)Verifique las versiones actuales en crates.io.
Carga y guardado de imágenes
Empecemos con un ejemplo básico: abrir un archivo y guardar una copia:
use image::{GenericImageView, ImageFormat};
fn main() -> Result<(), Box<dyn std::error::Error>> { // Cargamos la imagen let img = image::open("input.jpg")?; // Mostramos las dimensiones println!("Ancho: {}, Alto: {}", img.width(), img.height()); // Guardamos en otro formato img.save("output.png")?; Ok(())}El método image::open detecta automáticamente el formato por la extensión o el contenido del archivo.
Cambio de tamaño (resize)
La función resize acepta un nuevo ancho y alto, así como un filtro de interpolación. Filtros disponibles: Nearest, Triangle, CatmullRom, Gaussian, Lanczos3 y otros.
use image::{imageops::FilterType, GenericImageView};
fn resize_image(path: &str, new_width: u32, new_height: u32) -> Result<(), Box<dyn std::error::Error>> { let img = image::open(path)?; // Cambiamos el tamaño con el filtro Lanczos3 (alta calidad) let resized = img.resize(new_width, new_height, FilterType::Lanczos3); // Guardamos el resultado resized.save("resized.jpg")?; println!("Tamaño cambiado: {}x{} → {}x{}", img.width(), img.height(), new_width, new_height); Ok(())}Consejo: Para procesamiento rápido use FilterType::Nearest (sin interpolación), para máxima calidad — Lanczos3.
Cambio de tamaño proporcional
Para mantener la relación de aspecto, use resize_to_fill (rellena el área) o resize_to_fit (ajusta al rectángulo):
use image::imageops::FilterType;
fn resize_proportional(path: &str, max_width: u32, max_height: u32) -> Result<(), Box<dyn std::error::Error>> { let img = image::open(path)?; // Ajustar al rectángulo (manteniendo proporciones) let fitted = img.resize_to_fit(max_width, max_height, FilterType::Triangle); fitted.save("fitted.jpg")?; // Rellenar el área (recortará el sobrante) let filled = img.resize_to_fill(max_width, max_height, FilterType::Triangle); filled.save("filled.jpg")?; Ok(())}Recorte de imagen (crop)
El recorte se realiza mediante el método crop, que acepta las coordenadas de la esquina superior izquierda (x, y) y las dimensiones del área:
use image::Gener