image для Rust: полное руководство с примерами

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

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

Начать курс

Библиотека image для Rust: полное руководство

Библиотека image — это основная и наиболее популярная библиотека для работы с изображениями в экосистеме Rust. Она предоставляет мощный, безопасный и высокопроизводительный инструментарий для загрузки, обработки, анализа и сохранения растровых изображений. В отличие от многих C/C++ аналогов, image написана на чистом Rust, что гарантирует безопасность памяти и отсутствие утечек, характерных для низкоуровневых библиотек.

Зачем нужна эта библиотека? В современном мире обработка изображений требуется повсеместно: от веб-сервисов (генерация превью, наложение водяных знаков) до десктопных приложений (фоторедакторы, просмотрщики) и даже встраиваемых систем (компьютерное зрение на Raspberry Pi). image позволяет решать эти задачи без привязки к внешним C-библиотекам (как libpng или libjpeg), что упрощает сборку проекта и делает его кроссплатформенным "из коробки".

Библиотека поддерживает десятки форматов (PNG, JPEG, GIF, BMP, TIFF, WebP, ICO и другие), предоставляет доступ к отдельным пикселям, умеет изменять размеры, обрезать, вращать, инвертировать цвета и применять фильтры. В основе лежит трейт GenericImageView, который позволяет единообразно работать с любым типом изображения. Благодаря дизайну Rust, вы получаете максимальную производительность без ущерба для безопасности.

Установка

Для добавления библиотеки image в проект на Rust необходимо добавить её в файл Cargo.toml:

[dependencies]
image = "0.25"

После этого выполните команду cargo build. Cargo автоматически загрузит библиотеку и все её зависимости. Для работы с конкретными форматами (например, WebP или AVIF) могут потребоваться дополнительные feature-флаги, но для базового использования достаточно стандартной конфигурации.

Быстрый старт

Минимальный рабочий пример — загрузить изображение, изменить его размер и сохранить:

use image::{GenericImageView, imageops};

fn main() -> Result<(), image::ImageError> {
    // 1. Загружаем изображение из файла
    let img = image::open("input.jpg")?;
    
    // 2. Изменяем размер до 300x200 пикселей
    let resized = imageops::resize(&img, 300, 200, imageops::FilterType::Lanczos3);
    
    // 3. Сохраняем результат в PNG
    resized.save("output.png")?;
    
    println!("Изображение успешно обработано!");
    Ok(())
}

Этот код открывает файл input.jpg, изменяет его размер до 300x200 пикселей с использованием фильтра Lanczos3 (один из самых качественных) и сохраняет результат как output.png. Обратите внимание на обработку ошибок через Result — это идиоматичный подход в Rust.

Основные методы и функции

1. image::open

Сигнатура: pub fn open<P: AsRef<Path>>(path: P) -> ImageResult<DynamicImage>

Описание: Загружает изображение из файла, автоматически определяя формат по расширению или содержимому. Возвращает DynamicImage — перечисление, которое может содержать изображение любого поддерживаемого типа (Rgb8, Rgba8, Gray8 и т.д.).

Пример:

match image::open("photo.png") {
    Ok(img) => println!("Изображение загружено, размер: {}x{}", img.width(), img.height()),
    Err(e) => eprintln!("Ошибка загрузки: {}", e),
}

2. DynamicImage::to_rgb8 и to_rgba8

Сигнатура: pub fn to_rgb8(&self) -> ImageBuffer<Rgb<u8>, Vec<u8>>

Описание: Конвертирует динамическое изображение в конкретный тип пикселей. to_rgb8 — в RGB (3 канала), to_rgba8 — в RGBA (4 канала с альфа-каналом). Это необходимо для доступа к пикселям или применения некоторых операций.

Пример:

let img = image::open("input.png").unwrap();
let rgb_img = img.to_rgb8();
let pixel = rgb_img.get_pixel(10, 20);
println!("Пиксель (10,20): R={}, G={}, B={}", pixel[0], pixel[1], pixel[2]);

3. GenericImageView::get_pixel

Сигнатура: fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel

Описание: Возвращает значение пикселя по координатам (x, y). Координаты отсчитываются от верхнего левого угла. Тип пикселя зависит от типа изображения (например, Rgba<u8>).

Пример:

let img = image::open("photo.jpg").unwrap();
let pixel = img.get_pixel(0, 0); // Первый пиксель
println!("RGBA: {:?}", pixel.0); // Вывод: [R, G, B, A]

4. GenericImageView::width и height

Сигнатура: fn width(&self) -> u32 и fn height(&self) -> u32

Описание: Возвращают ширину и высоту изображения в пикселях. Полезно для итерации по всем пикселям или проверки размеров перед обработкой.

Пример:

let img = image::open("test.png").unwrap();
println!("Размер: {}x{}", img.width(), img.height());

5. imageops::resize

Сигнатура: pub fn resize<I: GenericImageView>(image: &I, nwidth: u32, nheight: u32, filter: FilterType) -> ImageBuffer<I::Pixel, Vec<I::Subpixel>>

Описание: Изменяет размер изображения до указанных ширины и высоты. Параметр filter определяет алгоритм интерполяции: Nearest (быстрый, но низкое качество), Triangle, CatmullRom, Lanczos3 (самый качественный, но медленный).

Пример:

use image::imageops;
let img = image::open("large.jpg").unwrap();
let thumbnail = imageops::resize(&img, 150, 150, imageops::FilterType::Nearest);
thumbnail.save("thumb.jpg").unwrap();

6. imageops::crop

Сигнатура: pub fn crop<I: GenericImageView>(image: &I, x: u32, y: u32, width: u32, height: u32) -> SubImage<&I>

Описание: Вырезает прямоугольную область из изображения, начиная с координат (x, y) и заданной ширины/высоты. Возвращает SubImage, который можно сохранить или преобразовать в ImageBuffer.

Пример:

let img = image::open("photo.jpg").unwrap();
let cropped = imageops::crop(&img, 100, 50, 200, 150);
cropped.to_image().save("cropped.png").unwrap();

7. imageops::rotate90, rotate180, rotate270

Сигнатура: pub fn rotate90<I: GenericImageView>(image: &I) -> ImageBuffer<I::Pixel, Vec<I::Subpixel>>

Описание: Поворачивают изображение на 90, 180 или 270 градусов соответственно. Работают без потери качества (не используют интерполяцию).

Пример:

let img = image::open("portrait.jpg").unwrap();
let rotated = imageops::rotate90(&img);
rotated.save("landscape.jpg").unwrap();

8. imageops::flip_horizontal и flip_vertical

Сигнатура: pub fn flip_horizontal<I: GenericImageView>(image: &I) -> ImageBuffer<I::Pixel, Vec<I::Subpixel>>

Описание: Отражают изображение по горизонтали (зеркально) или по вертикали. Полезно для создания симметричных эффектов или коррекции ориентации.

Пример:

let img = image::open("mirror.png").unwrap();
let flipped = imageops::flip_horizontal(&img);
flipped.save("flipped.png").unwrap();

9. imageops::grayscale

Сигнатура: pub fn grayscale<I: GenericImageView>(image: &I) -> GrayImage

Описание: Преобразует цветное изображение в оттенки серого. Использует стандартные коэффициенты яркости (0.299R + 0.587G + 0.114B).

Пример:

let img = image::open("colorful.jpg").unwrap();
let gray = imageops::grayscale(&img);
gray.save("black_and_white.jpg").unwrap();

10. imageops::blur

Сигнатура: pub fn blur<I: GenericImageView>(image: &I, sigma: f32) -> ImageBuffer<I::Pixel, Vec<I::Subpixel>>

Описание: Применяет гауссово размытие с заданным радиусом (sigma). Чем больше sigma, тем сильнее размытие. Используется для сглаживания, шумоподавления или создания эффекта "боке".

Пример:

let img = image::open("sharp.jpg").unwrap();
let blurred = imageops::blur(&img, 5.0);
blurred.save("blurred.jpg").unwrap();

11. imageops::contrast

Сигнатура: pub fn contrast<I: GenericImageView>(image: &I, contrast: f32) -> ImageBuffer<I::Pixel, Vec<I::Subpixel>>

Описание: Регулирует контрастность изображения. Значение contrast: 0.0 — полностью серое изображение, 1.0 — оригинал, >1.0 — увеличение контраста.

Пример:

let img = image::open("flat.jpg").unwrap();
let high_contrast = imageops::contrast(&img, 2.0);
high_contrast.save("contrast.jpg").unwrap();

12. ImageBuffer::save

Сигнатура: pub fn save<Q: AsRef<Path>>(&self, path: Q) -> ImageResult<()>

Описание: Сохраняет изображение в файл. Формат определяется по расширению файла. Поддерживаются PNG, JPEG, BMP, GIF, TIFF и другие.

Пример:

let img = image::open("source.png").unwrap();
img.save("copy.jpg").unwrap(); // Конвертация из PNG в JPEG

Реальный практический пример

Создадим утилиту для пакетной обработки изображений: изменение размера, добавление водяного знака и конвертация в черно-белый формат.

use image::{GenericImageView, imageops, Rgba};
use std::path::Path;
use std::fs;

/// Функция для наложения водяного знака (текстового) в правом нижнем углу
fn add_watermark(img: &image::DynamicImage, text: &str) -> image::DynamicImage {
    let mut base = img.to_rgba8();
    let (width, height) = base.dimensions();
    
    // Простейшая реализация: рисуем прямоугольник с текстом (пиксельная манипуляция)
    // В реальном проекте используйте библиотеку imageproc для рисования текста
    let watermark_height = 30;
    let watermark_y = height.saturating_sub(watermark_height + 10);
    let watermark_x = 10;
    
    for y in watermark_y..height {
        for x in watermark_x..(watermark_x + text.len() as u32 * 8).min(width) {
            let pixel = base.get_pixel_mut(x, y);
            // Затемняем пиксель (имитация полупрозрачного фона)
            *pixel = Rgba([
                pixel[0].saturating_sub(30),
                pixel[1].saturating_sub(30),
                pixel[2].saturating_sub(30),
                200, // Альфа-канал
            ]);
        }
    }
    
    image::DynamicImage::ImageRgba8(base)
}

fn process_image(input_path: &Path, output_dir: &Path, max_width: u32) -> Result<(), Box<                    

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