Rust图像处理库stb_image的使用,支持高效加载和解析PNG、JPG、BMP等主流图片格式

Rust图像处理库stb_image的使用,支持高效加载和解析PNG、JPG、BMP等主流图片格式

rust-stb-image是Rust语言对stb_image库的绑定实现。stb_image是一个轻量级的C语言图像加载库,支持PNG、JPG、BMP等多种主流图片格式。

安装

在项目中添加stb_image依赖:

stb_image = "0.3.0"

或者运行命令:

cargo add stb_image

使用示例

下面是一个完整的示例代码,展示如何使用stb_image加载和解析图片:

use stb_image::image::{LoadResult, Image};

fn main() {
    // 加载图片文件
    let image_result = Image::load("example.png");
    
    match image_result {
        LoadResult::ImageU8(image) => {
            // 成功加载8位图像
            println!("成功加载图片: {}x{} ({} channels)", 
                image.width, image.height, image.depth);
            
            // 访问像素数据
            for y in 0..image.height {
                for x in 0..image.width {
                    let index = (y * image.width + x) * image.depth as usize;
                    let r = image.data[index];
                    let g = image.data[index + 1];
                    let b = image.data[index + 2];
                    
                    // 处理像素数据...
                }
            }
        }
        LoadResult::ImageF32(image) => {
            // 成功加载32位浮点图像
            println!("成功加载浮点图像: {}x{} ({} channels)", 
                image.width, image.height, image.depth);
        }
        LoadResult::Error(error) => {
            // 加载失败
            eprintln!("加载图片失败: {}", error);
        }
    }
}

完整示例demo

下面是一个更完整的示例,展示如何加载图片并将其转换为灰度图:

use stb_image::image::{LoadResult, Image};

fn main() {
    // 加载图片文件
    let image_result = Image::load("input.jpg");
    
    match image_result {
        LoadResult::ImageU8(mut image) => {
            println!("成功加载图片: {}x{} ({}通道)", 
                image.width, image.height, image.depth);
            
            // 转换为灰度图
            if image.depth >= 3 {
                for i in (0..image.data.len()).step_by(image.depth as usize) {
                    let r = image.data[i] as f32;
                    let g = image.data[i + 1] as f32;
                    let b = image.data[i + 2] as f32;
                    
                    // 计算灰度值 (使用标准灰度转换公式)
                    let gray = (0.299 * r + 0.587 * g + 0.114 * b) as u8;
                    
                    // 将RGB通道都设为灰度值
                    image.data[i] = gray;
                    image.data[i + 1] = gray;
                    image.data[i + 2] = gray;
                    
                    // 如果有alpha通道,保持不变
                    if image.depth == 4 {
                        // alpha通道保持不变
                    }
                }
                
                // 保存处理后的图片
                if let Err(e) = image.save("output.jpg") {
                    eprintln!("保存图片失败: {}", e);
                } else {
                    println!("灰度图已保存为output.jpg");
                }
            }
        }
        LoadResult::ImageF32(_) => {
            println!("暂不支持浮点图像处理");
        }
        LoadResult::Error(error) => {
            eprintln!("加载图片失败: {}", error);
        }
    }
}

功能特点

  1. 支持多种图片格式:PNG、JPG、BMP等
  2. 高效的内存使用
  3. 简单的API接口
  4. 支持8位和32位浮点图像加载

注意事项

  • 当前版本使用修改版的stb_image v2.28
  • 图像数据处理时需要注意通道顺序(RGBA)
  • 处理图片时要注意边界检查和通道数验证

这个库特别适合需要轻量级图像加载功能的Rust项目,是游戏开发、计算机视觉等应用的理想选择。


1 回复

Rust图像处理库stb_image的使用指南

stb_image是一个轻量级的图像加载库,Rust版本提供了对主流图片格式(PNG、JPG、BMP等)的高效加载和解析支持。

特性

  • 支持多种图片格式:JPEG、PNG、BMP、PSD、TGA、GIF等
  • 无外部依赖
  • 内存占用小
  • 简单易用的API

使用方法

添加依赖

Cargo.toml中添加:

[dependencies]
stb_image = "0.2"

基本用法示例

use stb_image::image;

fn main() {
    // 加载图片
    let image = image::load("example.jpg");
    
    match image {
        image::LoadResult::ImageU8(image) => {
            println!("Loaded image: {}x{} ({} channels)", 
                    image.width, 
                    image.height, 
                    image.depth);
            
            // 访问像素数据
            let pixel_data = image.data;
            // 处理像素数据...
        }
        image::LoadResult::ImageF32(image) => {
            println!("Loaded HDR image");
            // 处理HDR图像...
        }
        image::LoadResult::Error(e) => {
            eprintln!("Failed to load image: {}", e);
        }
    }
}

高级选项

use stb_image::image::{load_with_depth, DesiredChannels};

// 强制加载为RGB格式(3通道)
let image = load_with_depth("example.png", DesiredChannels::RGB, 3);

// 强制加载为RGBA格式(4通道)
let image = load_with_depth("example.png", DesiredChannels::RGBA, 4);

// 加载时不进行自动翻转
let image = image::load_with_flip("example.jpg", false);

保存图像

use stb_image::image::save;

// 保存为PNG格式
let pixels = vec![255, 0, 0, 255]; // 红色像素(RGBA)
save("output.png", 1, 1, 4, &pixels).unwrap();

完整示例demo

下面是一个完整的使用stb_image加载、处理和保存图像的示例:

use stb_image::image::{load, load_with_depth, DesiredChannels, save};

fn main() {
    // 1. 基本加载示例
    println!("=== 基本加载示例 ===");
    let image = load("example.jpg");
    
    match image {
        image::LoadResult::ImageU8(img) => {
            println!("成功加载图像: {}x{} ({}通道)", 
                    img.width, 
                    img.height, 
                    img.depth);
            
            // 2. 处理图像数据 - 这里简单地将图像转为灰度
            println!("\n=== 图像处理示例 ===");
            let mut gray_data = Vec::with_capacity(img.width * img.height);
            
            for i in 0..img.data.len() / img.depth {
                let r = img.data[i * img.depth] as f32;
                let g = img.data[i * img.depth + 1] as f32;
                let b = img.data[i * img.depth + 2] as f32;
                
                // 计算灰度值
                let gray = (0.299 * r + 0.587 * g + 0.114 * b) as u8;
                gray_data.push(gray);
            }
            
            // 3. 保存处理后的图像
            println!("\n=== 保存图像示例 ===");
            save("gray_image.png", img.width, img.height, 1, &gray_data)
                .expect("保存图像失败");
            println!("灰度图像已保存为 gray_image.png");
        }
        image::LoadResult::ImageF32(_) => {
            println!("加载了HDR图像,本示例不支持");
        }
        image::LoadResult::Error(e) => {
            eprintln!("加载图像失败: {}", e);
        }
    }

    // 4. 高级选项示例 - 强制加载为3通道RGB
    println!("\n=== 高级选项示例 ===");
    let rgb_image = load_with_depth("example.png", DesiredChannels::RGB, 3);
    if let image::LoadResult::ImageU8(img) = rgb_image {
        println!("强制加载为RGB图像成功: {}x{} ({}通道)", 
                img.width, img.height, img.depth);
    }
}

注意事项

  1. 默认情况下,图像会被垂直翻转以适应OpenGL的纹理坐标系统
  2. 对于HDR图像,会返回ImageF32类型
  3. 图像数据以行优先顺序存储

性能提示

  • 对于需要频繁加载的图像,考虑缓存加载结果
  • 只加载需要的通道数可以减少内存使用
  • 对于已知格式的图像,可以使用特定格式的加载函数提高性能

这个库非常适合需要轻量级图像加载功能的Rust项目,特别是在嵌入式或资源受限的环境中。

回到顶部