使用 Rust 和 Slint 构建交互式颜色拾取器
项目实现
本文展示如何使用 Rust 语言结合 Slint UI 框架构建一个交互式的颜色拾取器应用程序。
运行效果
项目结构
核心代码实现
Cargo.toml 配置
[package]
name = "color-picker"
version = "0.1.0"
edition = "2021"
[dependencies]
image = "0.25.9"
slint = "1.14.1"
[build-dependencies]
slint-build = "1.14.1"
主程序逻辑 (main.rs)
use slint::PlatformError;
slint::include_modules!();
fn main() -> Result<(), PlatformError> {
let ui_app = MainWindow::new()?;
let ui_handle = ui_app.as_weak();
let canvas_width = ui_app.get_canvas_width() as u32;
let canvas_height = ui_app.get_canvas_height() as u32;
// 加载色彩轮图像
let image_path = "ui/assets/color-wheel.png";
let mut resource_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
resource_path.push(image_path);
let source_bitmap = image::open(&resource_path)
.expect("无法加载图像文件")
.into_rgba8();
let scaled_bitmap = image::imageops::resize(
&source_bitmap,
canvas_width,
canvas_height,
image::imageops::FilterType::Lanczos3
);
// 设置UI图像资源
ui_app.set_color_wheel(slint::Image::from_rgba8(
slint::SharedPixelBuffer::clone_from_slice(
scaled_bitmap.as_raw(),
canvas_width,
canvas_height,
),
));
// 处理用户交互事件
ui_app.on_cursor_dragged({
let app_ref = ui_app.clone_strong();
move |pos_x: i32, pos_y| {
if let Some(pixel_data) = scaled_bitmap.get_pixel_checked(pos_x as u32, pos_y as u32) {
app_ref.set_selected_color(slint::Brush::from(slint::Color::from_argb_u8(
pixel_data[3], // Alpha
pixel_data[0], // Red
pixel_data[1], // Green
pixel_data[2] // Blue
)));
}
}
});
ui_app.run()
}
界面定义 (main.slint)
import { VerticalBox, HorizontalBox } from "std-widgets.slint";
export component MainWindow inherits Window {
width: 800px;
height: 600px;
callback cursor_dragged(int, int);
in property <image> color-wheel <=> wheel_display.source;
out property <length> canvas-width <=> wheel_display.width;
out property <length> canvas-height <=> wheel_display.height;
in property <brush> selected-color <=> preview_panel.background;
wheel_display := Image {
width: 400px;
height: 400px;
image-fit: fill;
TouchArea {
pointer-event(event) => {
if event.kind == PointerEventKind.down || event.kind == PointerEventKind.move {
cursor_dragged(self.mouse-x as int, self.mouse-y as int);
}
}
}
}
preview_panel := Rectangle {
y: parent.height - self.height;
width: parent.width;
height: 60px;
border-width: 1px;
border-color: #cccccc;
}
}
图像处理库详解
本项目使用 image crate 实现图像处理功能,该库为 Rust 生态系统提供了全面的图像编解码和处理能力。
库功能概览
- 多格式支持: 支持 JPEG、PNG、BMP、GIF、WebP 等主流图像格式
- 高效处理: 利用 Rust 的零成本抽象实现高性能图像操作
- 类型安全: 通过泛型和 trait 系统确保编译期类型检查
- 内存优化: 提供多种像素存储方式以适应不同场景需求
核心数据结构
| 类型 | 用途 |
|---|---|
DynamicImage | 统一表示各种颜色格式的图像枚举类型 |
ImageBuffer | 泛型图像缓冲区,支持自定义像素和存储类型 |
RgbImage | 8位RGB颜色图像的类型别名 |
RgbaImage | 8位RGBA颜色图像的类型别名 |
常用操作示例
use image::{ImageFormat, io::Reader as ImageReader};
// 图像加载与解码
let img_reader = ImageReader::open("sample.png")?;
let dynamic_img = img_reader.decode()?;
// 尺寸调整
let resized = image::imageops::resize(
&dynamic_img.to_rgb8(),
800,
600,
image::imageops::FilterType::Triangle
);
// 像素级操作
let (width, height) = resized.dimensions();
for y in 0..height {
for x in 0..width {
let pixel = resized.get_pixel(x, y);
// 处理像素数据
}
}
// 图像保存
resized.save_with_format("output.jpg", ImageFormat::Jpeg)?;
高级处理能力
通过 imageops 模块可实现复杂图像变换:
- 几何变换: 缩放、旋转、翻转
- 色彩调整: 亮度、对比度、色调调节
- 滤镜效果: 高斯模糊、边缘检测
- 图像合成: 图层混合、透明度处理