realsense_rust/processing_blocks/
colorizer.rs

1//! Processing block for colorizing depth data
2//!
3//! The colorizer converts depth frames to RGB format for visualization
4
5use crate::{
6    check_rs2_error,
7    frame::{ColorFrame, DepthFrame, FrameEx},
8    processing_blocks::{
9        errors::{ProcessFrameError, ProcessingBlockConstructionError},
10        options::{
11            get_processing_block_option, get_processing_block_option_range,
12            set_processing_block_option, ColorizerOptions, OptionsExt, ProcessingBlockOptionError,
13        },
14    },
15};
16use anyhow::Result;
17use realsense_sys as sys;
18use std::{convert::TryFrom, ptr::NonNull, task::Poll, time::Duration};
19
20/// Creates Depth-Colorizer processing block that can be used to quickly visualize the depth data
21/// This block accepts depth frames as input and replaces them by depth frames with format RGB8
22/// Non-depth frames are passed through
23#[derive(Debug, Clone)]
24pub struct Colorizer {
25    /// The processing block for colorizing depth frames
26    processing_block: NonNull<sys::rs2_processing_block>,
27    /// The frame queue upon which the processing block will deposit colorized frames
28    processing_queue: NonNull<sys::rs2_frame_queue>,
29}
30
31impl Drop for Colorizer {
32    fn drop(&mut self) {
33        unsafe {
34            sys::rs2_delete_frame_queue(self.processing_queue.as_ptr());
35            sys::rs2_delete_processing_block(self.processing_block.as_ptr());
36        }
37    }
38}
39
40impl Colorizer {
41    /// Create a new Colorizer processing block
42    pub fn new(processing_queue_size: i32) -> Result<Self, ProcessingBlockConstructionError> {
43        let (processing_block, processing_queue) = unsafe {
44            let mut err = std::ptr::null_mut::<sys::rs2_error>();
45
46            let ptr = sys::rs2_create_colorizer(&mut err);
47            check_rs2_error!(
48                err,
49                ProcessingBlockConstructionError::CouldNotCreateProcessingBlock
50            )?;
51
52            let queue_ptr = sys::rs2_create_frame_queue(processing_queue_size, &mut err);
53            check_rs2_error!(
54                err,
55                ProcessingBlockConstructionError::CouldNotCreateProcessingQueue
56            )?;
57
58            sys::rs2_start_processing_queue(ptr, queue_ptr, &mut err);
59            check_rs2_error!(
60                err,
61                ProcessingBlockConstructionError::CouldNotStartProcessingQueue
62            )?;
63            (NonNull::new(ptr).unwrap(), NonNull::new(queue_ptr).unwrap())
64        };
65
66        Ok(Self {
67            processing_block,
68            processing_queue,
69        })
70    }
71
72    /// Process a depth frame and colorize it
73    pub fn queue(&mut self, frame: DepthFrame) -> Result<(), ProcessFrameError> {
74        unsafe {
75            let mut err = std::ptr::null_mut::<sys::rs2_error>();
76            sys::rs2_process_frame(
77                self.processing_block.as_ptr(),
78                frame.get_owned_raw().as_ptr(),
79                &mut err,
80            );
81            check_rs2_error!(err, |kind, context| { ProcessFrameError { kind, context } })?;
82            Ok(())
83        }
84    }
85
86    /// Wait to receive the colorized frame results
87    pub fn wait(&mut self, timeout: Duration) -> Result<ColorFrame, ProcessFrameError> {
88        unsafe {
89            let mut err = std::ptr::null_mut::<sys::rs2_error>();
90            let timeout_millis = u32::try_from(timeout.as_millis()).unwrap_or(u32::MAX);
91
92            let colorized_frame =
93                sys::rs2_wait_for_frame(self.processing_queue.as_ptr(), timeout_millis, &mut err);
94            check_rs2_error!(err, |kind, context| { ProcessFrameError { kind, context } })?;
95            Ok(ColorFrame::try_from(NonNull::new(colorized_frame).unwrap()).unwrap())
96        }
97    }
98
99    /// Poll to receive the colorized frame results
100    pub fn poll(&mut self) -> Result<Poll<ColorFrame>, ProcessFrameError> {
101        unsafe {
102            let mut err = std::ptr::null_mut::<sys::rs2_error>();
103            let mut frame = std::ptr::null_mut::<sys::rs2_frame>();
104            let is_ready =
105                sys::rs2_poll_for_frame(self.processing_queue.as_ptr(), &mut frame, &mut err);
106
107            // Check for errors
108            check_rs2_error!(err, |kind, context| { ProcessFrameError { kind, context } })?;
109
110            // Check for queue readiness
111            if is_ready == 0 {
112                Ok(Poll::Pending)
113            } else {
114                Ok(Poll::Ready(
115                    ColorFrame::try_from(NonNull::new(frame).unwrap()).unwrap(),
116                ))
117            }
118        }
119    }
120
121    /// Apply options to configure the colorizer
122    pub fn apply_options(
123        &mut self,
124        options: &ColorizerOptions,
125    ) -> Result<(), ProcessingBlockOptionError> {
126        if let Some(color_scheme) = options.color_scheme {
127            self.set_option(sys::rs2_option_RS2_OPTION_COLOR_SCHEME, color_scheme)?;
128        }
129        if let Some(histogram_equalization) = options.histogram_equalization {
130            self.set_option(
131                sys::rs2_option_RS2_OPTION_HISTOGRAM_EQUALIZATION_ENABLED,
132                histogram_equalization,
133            )?;
134        }
135        if let Some(min_distance) = options.min_distance {
136            self.set_option(sys::rs2_option_RS2_OPTION_MIN_DISTANCE, min_distance)?;
137        }
138        if let Some(max_distance) = options.max_distance {
139            self.set_option(sys::rs2_option_RS2_OPTION_MAX_DISTANCE, max_distance)?;
140        }
141        Ok(())
142    }
143}
144
145impl OptionsExt for Colorizer {
146    fn set_option(
147        &mut self,
148        option: sys::rs2_option,
149        value: f32,
150    ) -> Result<(), ProcessingBlockOptionError> {
151        set_processing_block_option(self.processing_block, option, value)
152    }
153
154    fn get_option(&self, option: sys::rs2_option) -> Result<f32, ProcessingBlockOptionError> {
155        get_processing_block_option(self.processing_block, option)
156    }
157
158    fn supports_option(&self, option: sys::rs2_option) -> bool {
159        unsafe {
160            let mut err = std::ptr::null_mut::<sys::rs2_error>();
161            let is_supported = sys::rs2_supports_option(
162                self.processing_block.as_ptr() as *const sys::rs2_options,
163                option,
164                &mut err,
165            );
166            err.is_null() && is_supported != 0
167        }
168    }
169
170    fn get_option_range(
171        &self,
172        option: sys::rs2_option,
173    ) -> Result<(f32, f32, f32, f32), ProcessingBlockOptionError> {
174        get_processing_block_option_range(self.processing_block, option)
175    }
176}