Обработка изображений на Rust: resize и crop с image и imageproc

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Обработка изображений на Rust: resize и crop

Rust — это современный системный язык программирования, который всё чаще применяется для задач, требующих высокой производительности и надёжности. Обработка изображений не исключение. В этой статье мы рассмотрим две ключевые операции — изменение размера (resize) и обрезку (crop) — с использованием экосистемы Rust. Основные библиотеки: image (загрузка, сохранение, базовые манипуляции) и imageproc (продвинутая обработка).

Почему Rust для работы с изображениями?

Rust предлагает:

  • Безопасную работу с памятью — отсутствие утечек и гонок данных.
  • Максимальную производительность — сравнимую с C/C++.
  • Богатую экосистему — crate image поддерживает JPEG, PNG, GIF, BMP, WEBP и другие форматы.
  • Параллелизм — легко масштабировать обработку на многоядерных процессорах.

Установка зависимостей

Добавьте в Cargo.toml:

[dependencies]
image = "0.25"
imageproc = "0.25"  # для продвинутых фильтров (опционально)

Актуальные версии уточняйте на crates.io.

Загрузка и сохранение изображения

Начнём с базового примера — открыть файл и сохранить его копию:

use image::{GenericImageView, ImageFormat};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Загружаем изображение
    let img = image::open("input.jpg")?;
    
    // Выводим размеры
    println!("Ширина: {}, Высота: {}", img.width(), img.height());
    
    // Сохраняем в другом формате
    img.save("output.png")?;
    Ok(())
}

Метод image::open автоматически определяет формат по расширению или содержимому файла.

Изменение размера (resize)

Функция resize принимает новые ширину и высоту, а также фильтр интерполяции. Доступные фильтры: Nearest, Triangle, CatmullRom, Gaussian, Lanczos3 и другие.

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)?;
    
    // Изменяем размер с фильтром Lanczos3 (высокое качество)
    let resized = img.resize(new_width, new_height, FilterType::Lanczos3);
    
    // Сохраняем результат
    resized.save("resized.jpg")?;
    println!("Размер изменён: {}x{} → {}x{}", img.width(), img.height(), new_width, new_height);
    Ok(())
}

Совет: Для быстрой обработки используйте FilterType::Nearest (нет интерполяции), для максимального качества — Lanczos3.

Пропорциональное изменение размера

Чтобы сохранить соотношение сторон, используйте resize_to_fill (заполняет область) или resize_to_fit (вписывает в прямоугольник):

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)?;
    
    // Вписать в прямоугольник (сохраняя пропорции)
    let fitted = img.resize_to_fit(max_width, max_height, FilterType::Triangle);
    fitted.save("fitted.jpg")?;
    
    // Заполнить область (обрежет лишнее)
    let filled = img.resize_to_fill(max_width, max_height, FilterType::Triangle);
    filled.save("filled.jpg")?;
    
    Ok(())
}

Обрезка изображения (crop)

Обрезка выполняется через метод crop, который принимает координаты верхнего левого угла (x, y) и размеры области:

use image::GenericImageView;

fn crop_image(path: &str, x: u32, y: u32, width: u32, height: u32) -> Result<(), Box<dyn std::error::Error>> {
    let img = image::open(path)?;
    
    // Обрезаем область (x, y, ширина, высота)
    let cropped = img.crop(x, y, width, height);
    
    // Сохраняем
    cropped.save                    

Рекомендаций