Rust图像处理库io-surface的使用:高效实现跨平台图形渲染与界面开发

Rust图像处理库io-surface的使用:高效实现跨平台图形渲染与界面开发

安装

在项目目录中运行以下Cargo命令:

cargo add io-surface

或者在Cargo.toml中添加以下行:

io-surface = "0.16.1"

示例代码

以下是一个使用io-surface库进行跨平台图形渲染的完整示例:

use io_surface::IOSurface;
use core_foundation::base::TCFType;
use core_foundation::dictionary::CFDictionary;
use core_foundation::number::CFNumber;
use core_foundation::string::CFString;

fn create_io_surface(width: usize, height: usize) -> IOSurface {
    // 创建属性字典来配置IOSurface
    let mut keys = Vec::new();
    let mut values = Vec::new();
    
    // 设置宽度
    keys.push(unsafe { CFString::wrap_under_get_rule(kIOSurfaceWidth) });
    values.push(CFNumber::from(width as i32).as_CFType());
    
    // 设置高度
    keys.push(unsafe { CFString::wrap_under_get_rule(kIOSurfaceHeight) });
    values.push(CFNumber::from(height as i32).as_CFType());
    
    // 设置像素格式
    keys.push(unsafe { CFString::wrap_under_get_rule(kIOSurfacePixelFormat) });
    values.push(CFNumber::from(kCVPixelFormatType_32BGRA as i32).as_CFType());
    
    // 设置字节对齐
    keys.push(unsafe { CFString::wrap_under_get_rule(kIOSurfaceBytesPerRow) });
    values.push(CFNumber::from((width * 4) as i32).as_CFType());
    
    // 创建字典
    let dict = CFDictionary::from_CFType_pairs(&keys, &values);
    
    // 创建IOSurface
    unsafe { IOSurface::from_uncreated(IOSurfaceCreate(dict.as_concrete_TypeRef())) }
}

fn main() {
    // 创建一个512x512的IOSurface
    let surface = create_io_surface(512, 512);
    
    // 锁定Surface进行写入
    unsafe {
        let res = IOSurfaceLock(
            surface.as_concrete_TypeRef(),
            kIOSurfaceLockAvoidSync,
            std::ptr::null_mut()
        );
        
        if res == 0 {
            // 获取基地址和字节每行
            let base_addr = IOSurfaceGetBaseAddress(surface.as_concrete_TypeRef());
            let bytes_per_row = IOSurfaceGetBytesPerRow(surface.as_concrete_TypeRef());
            
            // 在这里进行像素数据操作...
            
            // 解锁Surface
            IOSurfaceUnlock(surface.as_concrete_TypeRef(), kIOSurfaceLockAvoidSync, std::ptr::null_mut());
        }
    }
    
    // 现在surface可以用于跨平台渲染
}

完整示例demo

以下是一个更完整的示例,展示如何使用io-surface进行实际的图形渲染:

use io_surface::IOSurface;
use core_foundation::base::TCFType;
use core_foundation::dictionary::CFDictionary;
use core_foundation::number::CFNumber;
use core_foundation::string::CFString;

// 创建IOSurface的辅助函数
fn create_io_surface(width: usize, height: usize) -> IOSurface {
    let mut keys = Vec::new();
    let mut values = Vec::new();
    
    // 设置IOSurface属性
    keys.push(unsafe { CFString::wrap_under_get_rule(kIOSurfaceWidth) });
    values.push(CFNumber::from(width as i32).as_CFType());
    
    keys.push(unsafe { CFString::wrap_under_get_rule(kIOSurfaceHeight) });
    values.push(CFNumber::from(height as i32).as_CFType());
    
    keys.push(unsafe { CFString::wrap_under_get_rule(kIOSurfacePixelFormat) });
    values.push(CFNumber::from(kCVPixelFormatType_32BGRA as i32).as_CFType());
    
    keys.push(unsafe { CFString::wrap_under_get_rule(kIOSurfaceBytesPerRow) });
    values.push(CFNumber::from((width * 4) as i32).as_CFType());
    
    let dict = CFDictionary::from_CFType_pairs(&keys, &values);
    unsafe { IOSurface::from_uncreated(IOSurfaceCreate(dict.as_concrete_TypeRef())) }
}

// 在IOSurface上绘制简单图案
fn draw_on_surface(surface: &IOSurface) {
    unsafe {
        let res = IOSurfaceLock(
            surface.as_concrete_TypeRef(),
            kIOSurfaceLockAvoidSync,
            std::ptr::null_mut()
        );
        
        if res == 0 {
            let base_addr = IOSurfaceGetBaseAddress(surface.as_concrete_TypeRef()) as *mut u8;
            let bytes_per_row = IOSurfaceGetBytesPerRow(surface.as_concrete_TypeRef()) as usize;
            let width = IOSurfaceGetWidth(surface.as_concrete_TypeRef()) as usize;
            let height = IOSurfaceGetHeight(surface.as_concrete_TypeRef()) as usize;
            
            // 简单的渐变填充
            for y in 0..height {
                for x in 0..width {
                    let offset = y * bytes_per_row + x * 4;
                    let pixel = base_addr.add(offset);
                    
                    // BGRA格式
                    pixel.add(0).write((x as f32 / width as f32 * 255.0) as u8); // Blue
                    pixel.add(1).write((y as f32 / height as f32 * 255.0) as u8); // Green
                    pixel.add(2).write(128); // Red
                    pixel.add(3).write(255); // Alpha
                }
            }
            
            IOSurfaceUnlock(surface.as_concrete_TypeRef(), kIOSurfaceLockAvoidSync, std::ptr::null_mut());
        }
    }
}

fn main() {
    // 创建800x600的IOSurface
    let surface = create_io_surface(800, 600);
    
    // 在surface上绘制内容
    draw_on_surface(&surface);
    
    // 这里可以将surface传递给其他图形API进行渲染
    println!("成功创建并绘制了IOSurface");
}

关键特性

  1. 跨平台支持:io-surface提供了跨平台的图形表面抽象
  2. 高性能:直接与系统图形API交互,减少中间层开销
  3. 内存效率:智能管理图形内存
  4. 线程安全:支持多线程访问和渲染

许可证

本项目采用MIT或Apache-2.0双重许可证


1 回复

Rust图像处理库io-surface的使用:高效实现跨平台图形渲染与界面开发

完整示例Demo

下面是一个使用io-surface库实现简单图像渲染并显示在窗口中的完整示例:

use io_surface::IOSurface;
use winit::{
    event::{Event, WindowEvent},
    event_loop::{ControlFlow, EventLoop},
    window::WindowBuilder,
};
use std::ptr;

fn main() {
    // 创建事件循环和窗口
    let event_loop = EventLoop::new();
    let window = WindowBuilder::new()
        .with_title("Rust io-surface 示例")
        .with_inner_size(winit::dpi::LogicalSize::new(800, 600))
        .build(&event_loop)
        .unwrap();

    // 创建IOSurface
    let surface = IOSurface::new(800, 600, io_surface::PixelFormat::RGBA8, io_surface::ColorSpace::SRGB)
        .expect("创建IOSurface失败");

    // 渲染内容到surface
    render_to_surface(&surface).expect("渲染到surface失败");

    // 将surface附加到窗口
    attach_to_window(&window, &surface).expect("附加到窗口失败");

    // 运行事件循环
    event_loop.run(move |event, _, control_flow| {
        *control_flow = ControlFlow::Wait;

        match event {
            Event::WindowEvent {
                event: WindowEvent::CloseRequested,
                ..
            } => *control_flow = ControlFlow::Exit,
            _ => (),
        }
    });
}

fn render_to_surface(surface: &IOSurface) -> Result<(), io_surface::Error> {
    // 锁定表面进行写入
    surface.lock(
        io_surface::LockOptions::WRITE_ONLY,
        ptr::null_mut()
    )?;
    
    // 获取表面数据指针
    let data = surface.base_address() as *mut u8;
    let bytes_per_row = surface.bytes_per_row();
    
    // 渲染渐变效果
    for y in 0..600 {
        for x in 0..800 {
            let offset = (y * bytes_per_row + x * 4) as isize;
            unsafe {
                *data.offset(offset) = (x as f32 / 800.0 * 255.0) as u8;     // R - 水平渐变
                *data.offset(offset + 1) = (y as f32 / 600.0 * 255.0) as u8; // G - 垂直渐变
                *data.offset(offset + 2) = 128;                             // B - 固定值
                *data.offset(offset + 3) = 255;                             // A - 不透明
            }
        }
    }
    
    // 解锁表面
    surface.unlock()?;
    
    Ok(())
}

fn attach_to_window(window: &winit::window::Window, surface: &IOSurface) -> Result<(), io_surface::Error> {
    #[cfg(target_os = "macos")]
    {
        use cocoa::appkit::NSView;
        use cocoa::base::id;
        use objc::{msg_send, sel, sel_impl};
        
        let ns_window = window.ns_window() as id;
        let ns_view: id = unsafe { msg_send![ns_window, contentView] };
        
        // 将IOSurface附加到NSView
        unsafe {
            let layer: id = msg_send![surface.as_ptr(), layer];
            msg_send![ns_view, setLayer: layer];
            msg_send![ns_view, setWantsLayer: cocoa::base::YES];
        }
    }
    
    #[cfg(target_os = "windows")]
    {
        use winapi::shared::windef::HWND;
        use winapi::um::dcomp::{DCompositionCreateSurfaceHandle, DCompositionAttachSurface};
        
        let hwnd = window.hwnd() as HWND;
        
        let mut handle = std::ptr::null_mut();
        unsafe {
            DCompositionCreateSurfaceHandle(0, std::ptr::null_mut(), &mut handle);
            DCompositionAttachSurface(hwnd, handle);
        }
    }
    
    Ok(())
}

示例说明

  1. 这个完整示例演示了如何:

    • 创建一个窗口
    • 初始化IOSurface
    • 在surface上渲染渐变效果
    • 将surface附加到窗口显示
    • 处理窗口事件
  2. 主要功能模块:

    • main(): 初始化应用程序,创建窗口和事件循环
    • render_to_surface(): 负责在surface上绘制渐变效果
    • attach_to_window(): 处理平台特定的surface附加逻辑
  3. 运行效果:

    • 窗口会显示一个从左上角到右下角的红绿渐变图像
    • 蓝色通道保持固定值128
    • 图像完全不透明(alpha=255)

要运行此示例,请确保在Cargo.toml中添加了所有必要的依赖项:

[dependencies]
io-surface = "0.3"
winit = "0.28"
cocoa = { version = "0.24", features = ["metal"] }  # macOS需要
winapi = { version = "0.3", features = ["dcomp", "windef"] }  # Windows需要

这个示例展示了io-surface库的核心功能,包括图像渲染、内存管理和跨平台显示。您可以根据需要修改渲染逻辑或添加更复杂的图形操作。

回到顶部