-
-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathdirect_capture.rs
More file actions
109 lines (94 loc) · 4.21 KB
/
Copy pathdirect_capture.rs
File metadata and controls
109 lines (94 loc) · 4.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//! Direct capture test - captures at native resolution with MJPEG decode
//!
//! Run with: cargo run --example direct_capture
use nokhwa::pixel_format::RgbFormat;
use nokhwa::utils::{ApiBackend, CameraIndex, RequestedFormat, RequestedFormatType};
use nokhwa::{query, Camera};
use std::thread;
use std::time::Duration;
fn main() {
println!("═══════════════════════════════════════════════════════════════");
println!(" Direct Camera Capture Test");
println!("═══════════════════════════════════════════════════════════════\n");
// List cameras
println!("📋 Finding cameras...");
match query(ApiBackend::MediaFoundation) {
Ok(cameras) => {
for (i, cam) in cameras.iter().enumerate() {
println!(" [{}] {}", i, cam.human_name());
}
}
Err(e) => {
println!(" ❌ Failed: {}", e);
return;
}
}
// Create camera at highest resolution (which will give us MJPEG)
println!("\n📋 Creating camera (native resolution)...");
let requested_format =
RequestedFormat::new::<RgbFormat>(RequestedFormatType::AbsoluteHighestResolution);
let mut camera = match Camera::new(CameraIndex::Index(0), requested_format) {
Ok(cam) => {
println!(" ✅ Format: {:?}", cam.camera_format());
cam
}
Err(e) => {
println!(" ❌ Failed: {}", e);
return;
}
};
// Open stream
println!("\n📋 Opening stream (camera LED should turn on)...");
if let Err(e) = camera.open_stream() {
println!(" ❌ Failed: {}", e);
return;
}
println!(" ✅ Stream open");
// Wait for camera to stabilize
println!("\n📋 Warming up camera (3 seconds)...");
thread::sleep(Duration::from_secs(3));
// Capture a frame
println!("\n📋 Capturing frame...");
match camera.frame() {
Ok(frame) => {
let bytes = frame.buffer_bytes();
let width = frame.resolution().width_x;
let height = frame.resolution().height_y;
println!(" Raw: {}x{}, {} bytes", width, height, bytes.len());
// Check if MJPEG
if bytes.len() >= 3 && bytes[0] == 0xFF && bytes[1] == 0xD8 {
println!(" Format: MJPEG (will decode)");
match image::load_from_memory(&bytes) {
Ok(img) => {
let rgb = img.to_rgb8();
println!(" Decoded: {}x{} RGB", rgb.width(), rgb.height());
// Save
match rgb.save("direct_capture.jpg") {
Ok(_) => println!(" ✅ Saved to direct_capture.jpg"),
Err(e) => println!(" ❌ Save failed: {}", e),
}
}
Err(e) => println!(" ❌ Decode failed: {}", e),
}
} else {
println!(" Format: Raw RGB");
// Check if valid
let nonzero = bytes.iter().filter(|&&b| b != 0).count();
let pct = (nonzero as f64 / bytes.len() as f64) * 100.0;
println!(" Non-zero pixels: {:.1}%", pct);
if let Some(img) = image::RgbImage::from_vec(width, height, bytes.to_vec()) {
match img.save("direct_capture.jpg") {
Ok(_) => println!(" ✅ Saved to direct_capture.jpg"),
Err(e) => println!(" ❌ Save failed: {}", e),
}
}
}
}
Err(e) => println!(" ❌ Capture failed: {}", e),
}
// Stop
println!("\n📋 Stopping stream...");
let _ = camera.stop_stream();
println!(" ✅ Done!");
println!("\n═══════════════════════════════════════════════════════════════");
}