Rust中如何调整图像大小并支持EXIF方向

“在Rust中处理图像时遇到两个问题:1)如何高效地调整图像尺寸?2)调整尺寸时如何保留EXIF方向信息?目前用image库能调整大小,但发现旋转后的图片方向会出错。求教正确的处理流程,是否需要结合exif库?最好能提供具体代码示例。”

2 回复

使用image库调整大小,结合exif库读取方向信息。示例代码:

use image::{imageops, DynamicImage};
use exif::{Reader, In};

let img = image::open("input.jpg")?;
let exif_data = std::fs::File::open("input.jpg")
    .and_then(|f| Reader::new().read_from_container(&mut std::io::BufReader::new(f))).ok();

let oriented_img = apply_orientation(img, exif_data);
let resized = oriented_img.resize(800, 600, imageops::FilterType::Lanczos3);
resized.save("output.jpg")?;

需实现apply_orientation函数根据EXIF方向旋转图像。


在Rust中调整图像大小并处理EXIF方向,可以使用以下方法:

主要依赖库

[dependencies]
image = "0.25"
exif = "0.9"

完整代码示例

use image::{ImageFormat, DynamicImage, imageops::FilterType};
use exif::{Reader, In, Tag};
use std::fs::File;
use std::io::BufReader;

fn adjust_image_with_exif(input_path: &str, output_path: &str, width: u32, height: u32) -> Result<(), Box<dyn std::error::Error>> {
    // 读取图像
    let img = image::open(input_path)?;
    
    // 读取EXIF数据
    let file = File::open(input_path)?;
    let mut buf_reader = BufReader::new(&file);
    let exif_reader = Reader::new().read_from_container(&mut buf_reader).ok();
    
    // 根据EXIF方向调整图像
    let oriented_img = if let Some(exif) = exif_reader {
        if let Some(orientation) = get_orientation(&exif) {
            apply_orientation(img, orientation)
        } else {
            img
        }
    } else {
        img
    };
    
    // 调整大小
    let resized_img = oriented_img.resize(width, height, FilterType::Lanczos3);
    
    // 保存图像
    resized_img.save(output_path)?;
    
    Ok(())
}

fn get_orientation(exif: &Reader) -> Option<u32> {
    if let Ok(field) = exif.get_field(Tag::Orientation, In::PRIMARY) {
        if let Some(value) = field.value.get_uint(0) {
            return Some(value);
        }
    }
    None
}

fn apply_orientation(img: DynamicImage, orientation: u32) -> DynamicImage {
    match orientation {
        1 => img, // 正常
        2 => img.fliph(), // 水平翻转
        3 => img.rotate180(), // 旋转180度
        4 => img.flipv(), // 垂直翻转
        5 => img.rotate90().fliph(), // 旋转90度+水平翻转
        6 => img.rotate90(), // 旋转90度
        7 => img.rotate270().fliph(), // 旋转270度+水平翻转
        8 => img.rotate270(), // 旋转270度
        _ => img, // 未知方向,保持原样
    }
}

使用示例

fn main() -> Result<(), Box<dyn std::error::Error>> {
    adjust_image_with_exif("input.jpg", "output.jpg", 800, 600)?;
    println!("图像调整完成!");
    Ok(())
}

关键点说明

  1. EXIF方向处理:读取Orientation标签,根据值进行相应的旋转和翻转
  2. 图像调整:使用resize方法,可选择不同的滤波算法
  3. 错误处理:使用Result类型进行错误传播

这种方法能正确处理大多数相机拍摄的图像方向问题,确保调整大小后的图像显示方向正确。

回到顶部