#display #screen-capture #graphics #color-space #displaystream #coregraphics

core-graphics2

到CoreGraphics框架的安全绑定,包括显示流

10个版本

0.3.3 2024年8月6日
0.3.2 2024年6月3日
0.3.1 2024年5月31日
0.2.0 2024年5月29日
0.1.5 2024年5月26日

#34 in 多媒体

Download history 171/week @ 2024-05-04 89/week @ 2024-05-11 131/week @ 2024-05-18 622/week @ 2024-05-25 295/week @ 2024-06-01 60/week @ 2024-06-08 58/week @ 2024-06-15 21/week @ 2024-06-22 1/week @ 2024-06-29 2/week @ 2024-07-06 20/week @ 2024-07-13 15/week @ 2024-07-20 34/week @ 2024-07-27 139/week @ 2024-08-03 50/week @ 2024-08-10

每月243次下载
用于 6 个crates(直接使用3个)

MIT/Apache

245KB
6K SLoC

core-graphics2

Version Documentation License License

Rust到CoreGraphics框架的安全绑定

示例

[dependencies]
core-graphics2 = { version = "0.1", default-features = false, features = ["display", "display-stream", "link"] }
use core_foundation::{
    base::{CFType, TCFType},
    boolean::CFBoolean,
    dictionary::CFMutableDictionary,
    number::CFNumber,
    string::CFString,
};
use core_graphics2::{
    color_space::{CGColorSpace, CGColorSpaceNames},
    display::CGDisplay,
    display_stream::*,
};
use core_video::pixel_buffer::{self, CVPixelBuffer};
use dispatch2::{Queue, QueueAttribute};
use io_surface::IOSurface;

let display = CGDisplay::main();
let output_width = display.pixels_wide();
let output_height = display.pixels_high();
let pixel_format = pixel_buffer::kCVPixelFormatType_420YpCbCr8BiPlanarFullRange;
let mut properties = CFMutableDictionary::<CFString, CFType>::new();
properties.add(&CGDisplayStreamProperties::ShowCursor.into(), &CFBoolean::true_value().as_CFType());
if let Some(color_space) = CGColorSpace::from_name(&CGColorSpaceNames::SRGB.into()) {
    properties.add(&CGDisplayStreamProperties::ColorSpace.into(), &color_space.as_CFType());
}
properties.add(&CGDisplayStreamProperties::MinimumFrameTime.into(), &CFNumber::from(1.0 / 60.0).as_CFType());
let ycbcr_matrix: CFString = CGDisplayStreamYCbCrMatrices::ITU_R_709_2.into();
properties.add(&CGDisplayStreamProperties::YCbCrMatrix.into(), &ycbcr_matrix.as_CFType());

let closure = move |status: CGDisplayStreamFrameStatus, timestamp: u64, surface: Option<IOSurface>, update: Option<CGDisplayStreamUpdate>| match status {
    CGDisplayStreamFrameStatus::Stopped => {
        println!("status: Stopped");
    }
    CGDisplayStreamFrameStatus::FrameComplete => {
        println!("status: {:?}, timestamp: {}", status, timestamp);
        if let Some(update) = update {
            println!("refreshed rects: {:?}", update.rects(CGDisplayStreamUpdateRectType::RefreshedRects));
            println!("moved rects: {:?}", update.rects(CGDisplayStreamUpdateRectType::MovedRects));
            println!("dirty rects: {:?}", update.rects(CGDisplayStreamUpdateRectType::DirtyRects));
            println!("reduced dirty rects: {:?}", update.rects(CGDisplayStreamUpdateRectType::ReducedDirtyRects));
        }
        if let Some(surface) = surface {
            if let Ok(pixel_buffer) = CVPixelBuffer::from_io_surface(&surface, None) {
                println!("pixel_buffer: {:?}", pixel_buffer);
            }
        }
    }
    _ => {}
};

let queue = Queue::new("com.screen_capture.queue", QueueAttribute::Serial);
if let Ok(display_stream) = CGDisplayStream::new_with_dispatch_queue(
        display.id,
        output_width,
        output_height,
        pixel_format as i32,
        &properties.to_immutable(),
        &queue,
        closure,
) {
    display_stream.start();
}

依赖项

~0.3–1.6MB
~19K SLoC