Working with Images in Rust: Overview of image, fast_image_resize, and other Libraries

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Working with Images in Rust: Overview of Libraries and Practical Examples



Rust is a modern systems programming language that is gaining popularity in areas requiring high performance and reliability. Image processing is no exception: the Rust ecosystem offers several mature libraries for loading, processing, converting, and analyzing images. In this article, we will look at the main tools: image, fast_image_resize, and photon-rs, and also provide code examples for typical tasks.



The Main Library: image



The image crate (version 0.25.x) is the de facto standard for working with images in Rust. It supports reading and writing many formats: PNG, JPEG, BMP, GIF, TIFF, WebP, and others. The library provides convenient data structures for representing images (DynamicImage, RgbImage, GrayImage) and a wide range of operations: resizing, cropping, rotating, filters, color space conversion.



Example of loading and saving an image with resizing:



use image::{DynamicImage, GenericImageView, imageops::FilterType};

fn resize_image(input_path: &str, output_path: &str, new_width: u32, new_height: u32) { let img = image::open(input_path).expect("Failed to open image"); let resized = img.resize_exact(new_width, new_height, FilterType::Lanczos3); resized.save(output_path).expect("Failed to save image"); println!("Image resized and saved to {}", output_path);}

fn main() { resize_image("input.jpg", "output.png", 800, 600);}


The image library also supports working with pixels directly. For example, you can access each pixel and change its color:



use image::{GenericImage, Rgba};

fn invert_colors(path: &str) { let mut img = image::open(path).expect("Error opening image"); for (x, y, pixel) in img.enumerate_pixels_mut() { let inverted = Rgba([ 255 - pixel[0], 255 - pixel[1], 255 - pixel[2], pixel[3], ]); img.put_pixel(x, y, inverted); } img.save("inverted.png").unwrap();}


High-Performance Resizing: fast_image_resize



If your task is to repeatedly resize images with maximum speed, check out the fast_image_resize crate. It uses SIMD instructions (SSE, AVX2, NEON) and optimized algorithms (Lanczos, Catmull-Rom, Mitchell). The library works directly with raw pixel arrays, minimizing overhead.



Example of using fast_image_resize:



use fast_image_resize as fr;use image::GenericImageView;

fn resize_fast(input_path: &str, output_path: &str, new_width: u32, new_height: u32) { // Load image via image let img = image::open(input_path).expect("Error opening image"); let (width, height) = img.dimensions(); let rgba = img.to_rgba8();

// Create a view for fast_image_resize let src_view = fr::ImageView::new(&rgba, width, height, fr::PixelType::U8x4); let mut dst_image = fr::Image::new(new_width, new_height, fr::PixelType::U8x4); let mut dst_view = dst_image.view_mut();

// Configure the resizer let mut resizer = fr::Resizer::new(fr::ResizeAlg::Convolution(fr::FilterType::Lanczos3)); resizer.resize(&src_view, &mut dst_view).expect("Resize error");

// Save the result via image let result_img = image::RgbaImage::from_raw(new_width, new_height, dst_image.into_vec()).unwrap(); result_img.save(output_path).unwrap();}


According to benchmarks, fast_image_resize can be 2-5 times faster than standard resizing

Recommendations