Rust BMP图像处理库tinybmp的使用,tinybmp提供轻量高效的BMP格式解析与操作功能
Rust BMP图像处理库tinybmp的使用
tinybmp是一个小型BMP解析器,主要针对嵌入式、无标准库(no-std)环境设计,但也适用于任何场景。该库主要用于将BMP图像绘制到embedded_graphics
的DrawTarget
上,也可用于解析BMP文件用于其他应用。
示例
将BMP图像绘制到embedded-graphics绘图目标
使用Bmp
结构体与embedded_graphics
的Image
结构体配合,可以在任何绘图目标上显示BMP文件。
use embedded_graphics::{image::Image, prelude::*};
use tinybmp::Bmp;
// 包含BMP文件数据
let bmp_data = include_bytes!("../tests/chessboard-8px-color-16bit.bmp");
// 解析BMP文件
let bmp = Bmp::from_slice(bmp_data).unwrap();
// 通过将图像包装在embedded-graphics `Image`中,在(10, 20)位置绘制图像
Image::new(&bmp, Point::new(10, 20)).draw(&mut display)?;
使用像素迭代器
Bmp::pixels
方法返回一个遍历BMP文件中所有像素的迭代器。BMP文件中的颜色会自动转换为embedded_graphics
中的一种颜色类型。
use embedded_graphics::{pixelcolor::Rgb888, prelude::*};
use tinybmp::Bmp;
// 包含BMP文件数据
let bmp_data = include_bytes!("../tests/chessboard-8px-24bit.bmp");
// 解析BMP文件
// 注意需要明确指定BMP文件中颜色将转换为何种颜色类型
let bmp = Bmp::<Rgb888>::from_slice(bmp_data).unwrap();
for Pixel(position, color) in bmp.pixels() {
println!("R: {}, G: {}, B: {} @ ({})", color.r(), color.g(), color.b(), position);
}
访问单个像素
Bmp::pixel
可用于获取单个像素的颜色。返回的颜色将自动转换为embedded_graphics
中的一种颜色类型。
use embedded_graphics::{pixelcolor::Rgb888, image::GetPixel, prelude::*};
use tinybmp::Bmp;
// 包含BMP文件数据
let bmp_data = include_bytes!("../tests/chessboard-8px-24bit.bmp");
// 解析BMP文件
// 注意需要明确指定BMP文件中颜色将转换为何种颜色类型
let bmp = Bmp::<Rgb888>::from_slice(bmp_data).unwrap();
let pixel = bmp.pixel(Point::new(3, 2));
assert_eq!(pixel, Some(Rgb888::WHITE));
注意:目前在使用RLE4或RLE8压缩索引位图时无法访问单个像素。对于这些格式,pixel()
函数将始终返回None
。
访问原始图像数据
对于大多数应用来说,Bmp
提供的高级访问已经足够。但如果需要更低级别的访问,可以使用RawBmp
结构体来访问BMP头信息和颜色表。
use embedded_graphics::prelude::*;
use tinybmp::{RawBmp, Bpp, Header, RawPixel, RowOrder, CompressionMethod};
let bmp = RawBmp::from_slice(include_bytes!("../tests/chessboard-8px-24bit.bmp"))
.expect("Failed to parse BMP image");
// 读取BMP头
assert_eq!(
bmp.header(),
&Header {
file_size: 314,
image_data_start: 122,
bpp: Bpp::Bits24,
image_size: Size::new(8, 8),
image_data_len: 192,
channel_masks: None,
row_order: RowOrder::BottomUp,
compression_method: CompressionMethod::Rgb,
}
);
// 获取图像像素坐标和值的迭代器并收集到向量中
let pixels: Vec<RawPixel> = bmp.pixels().collect();
// 示例图像为8x8px
assert_eq!(pixels.len(), 8 * 8);
// 也可以读取单个原始像素值
let pixel = bmp.pixel(Point::new(3, 2));
// 源图像中白色像素的原始值
assert_eq!(pixel, Some(0xFFFFFFu32));
完整示例代码
// 示例1: 绘制BMP图像到显示设备
use embedded_graphics::{image::Image, prelude::*};
use tinybmp::Bmp;
fn draw_bmp_to_display(display: &mut impl DrawTarget) -> Result<(), Box<dyn std::error::Error>> {
// 包含BMP文件数据
let bmp_data = include_bytes!("chessboard-8px-color-16bit.bmp");
// 解析BMP文件
let bmp = Bmp::from_slice(bmp_data)?;
// 在(10, 20)位置绘制图像
Image::new(&bmp, Point::new(10, 20)).draw(display)?;
Ok(())
}
// 示例2: 遍历像素信息
use embedded_graphics::{pixelcolor::Rgb888, prelude::*};
fn analyze_bmp_pixels() {
let bmp_data = include_bytes!("chessboard-8px-24bit.bmp");
let bmp = Bmp::<Rgb888>::from_slice(bmp_data).unwrap();
for Pixel(pos, color) in bmp.pixels() {
println!("Position: {:?}, Color: R:{}, G:{}, B:{}",
pos, color.r(), color.g(), color.b());
}
}
// 示例3: 访问原始BMP数据
fn inspect_raw_bmp() {
let bmp = RawBmp::from_slice(include_bytes!("chessboard-8px-24bit.bmp")).unwrap();
println!("BMP Header: {:?}", bmp.header());
println!("First pixel color: {:?}", bmp.pixel(Point::new(0, 0)));
}
安装
在项目目录中运行以下Cargo命令:
cargo add tinybmp
或者在Cargo.toml中添加以下行:
tinybmp = "0.6.0"
最低支持的Rust版本
tinybmp最低支持的Rust版本为1.71
或更高。
Rust BMP图像处理库tinybmp使用指南
简介
tinybmp是一个轻量级的Rust库,专门用于解析和操作BMP(位图)图像格式。它设计简洁高效,特别适合嵌入式系统和资源受限环境中的BMP图像处理需求。
主要特性
- 支持多种BMP格式解析
- 低内存占用
- 无标准库依赖(no_std兼容)
- 简单的API设计
使用方法
添加依赖
首先在Cargo.toml中添加tinybmp依赖:
[dependencies]
tinybmp = "0.7.0"
基本用法
解析BMP文件
use tinybmp::{Bmp, FileType, RawBmp};
// 从字节切片解析BMP
let bmp_data = include_bytes!("../tests/chessboard-8px-24bit.bmp");
let bmp = Bmp::from_slice(bmp_data).unwrap();
// 获取图像基本信息
println!("尺寸: {}x{}", bmp.width(), bmp.height());
println!("颜色深度: {}bpp", bmp.bpp());
访问像素数据
// 遍历所有像素
for pixel in bmp.pixels() {
println!("坐标: ({}, {}), 颜色: {:?}", pixel.x, pixel.y, pixel.color);
}
// 获取特定位置像素
if let Some(pixel) = bmp.try_get_pixel(10, 20) {
println!("(10,20)处像素: {:?}", pixel);
}
创建新BMP图像
use tinybmp::{Bmp, BmpBuilder, PixelColor};
use embedded_graphics::pixelcolor::Rgb888;
// 创建一个16x16的24位BMP
let mut builder = BmpBuilder::new()
.with_size(16, 16)
.with_bpp(24);
// 填充像素数据
for y in 0..16 {
for x in 0..16 {
let color = if (x + y) % 2 == 0 {
Rgb888::new(255, 0, 0) // 红色
} else {
Rgb888::new(0, 0, 255) // 蓝色
};
builder.set_pixel(x, y, color).unwrap();
}
}
// 生成BMP数据
let bmp_data = builder.build().unwrap();
与embedded-graphics集成
use embedded_graphics::{prelude::*, pixelcolor::Rgb888};
use tinybmp::Bmp;
let bmp_data = include_bytes!("../tests/chessboard-8px-24bit.bmp");
let bmp = Bmp::<Rgb888>::from_slice(bmp_data).unwrap();
// 在embedded-graphics中使用
display.draw_iter(bmp.pixels()).unwrap();
高级用法
处理不同颜色深度的BMP
use tinybmp::{Bmp, DynamicBmp};
// 自动检测颜色深度
let dynamic_bmp = DynamicBmp::from_slice(bmp_data).unwrap();
match dynamic_bmp {
DynamicBmp::Rgb16(bmp) => {
println!("16位RGB图像");
// 处理16位图像...
}
DynamicBmp::Rgb24(bmp) => {
println!("24位RGB图像");
// 处理24位图像...
}
DynamicBmp::Rgb32(bmp) => {
println!("32位RGB图像");
// 处理32位图像...
}
}
性能优化
let bmp = Bmp::from_slice(bmp_data).unwrap();
for y in 0..bmp.height() {
let row = bmp.row(y).unwrap();
for (x, pixel) in row.enumerate() {
// 处理每个像素...
}
}
注意事项
- tinybmp主要设计用于解析,对BMP创建的完整功能支持有限
- 对于非常规BMP格式可能支持不完整
- 在资源受限环境中使用时,注意检查解析结果
完整示例
以下是一个完整的BMP图像处理示例,包含读取、修改和保存功能:
use tinybmp::{Bmp, BmpBuilder, DynamicBmp};
use embedded_graphics::pixelcolor::Rgb888;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 读取BMP文件
let bmp_data = include_bytes!("image.bmp");
let bmp = DynamicBmp::from_slice(bmp_data)?;
// 2. 打印图像信息
println!("图像信息:");
match &bmp {
DynamicBmp::Rgb16(bmp) => {
println!("格式: 16位RGB");
println!("尺寸: {}x{}", bmp.width(), bmp.height());
}
DynamicBmp::Rgb24(bmp) => {
println!("格式: 24位RGB");
println!("尺寸: {}x{}", bmp.width(), bmp.height());
}
DynamicBmp::Rgb32(bmp) => {
println!("格式: 32位RGB");
println!("尺寸: {}x{}", bmp.width(), bmp.height());
}
}
// 3. 创建新图像(反转颜色)
let mut builder = BmpBuilder::new()
.with_size(bmp.width(), bmp.height())
.with_bpp(24);
for y in 0..bmp.height() {
for x in 0..bmp.width() {
let pixel = bmp.try_get_pixel(x, y)?;
let inverted = Rgb888::new(
255 - pixel.r(),
255 - pixel.g(),
255 - pixel.b()
);
builder.set_pixel(x, y, inverted)?;
}
}
// 4. 保存新图像
let new_bmp = builder.build()?;
std::fs::write("inverted.bmp", new_bmp.as_slice())?;
println!("图像处理完成,已保存为 inverted.bmp");
Ok(())
}
这个完整示例展示了如何:
- 读取BMP文件并自动检测其格式
- 获取图像的基本信息
- 创建新图像并对每个像素进行颜色反转处理
- 将处理后的图像保存到新文件
tinybmp是一个在Rust生态中处理BMP图像的轻量级解决方案,特别适合需要高效解析BMP而不需要复杂图像处理功能的场景。