diff --git a/nokhwa-core/src/buffer.rs b/nokhwa-core/src/buffer.rs index 4f2e6b4..c3f8661 100644 --- a/nokhwa-core/src/buffer.rs +++ b/nokhwa-core/src/buffer.rs @@ -97,96 +97,4 @@ impl Buffer { buffer, ) } - - /// Decodes a image with allocation using the provided [`FormatDecoder`] into a [`Mat`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html). - /// - /// Note that this does a clone when creating the buffer, to decouple the lifetime of the internal data to the temporary Buffer. If you want to avoid this, please see [`decode_as_opencv_mat`](Self::decode_as_opencv_mat). - /// # Errors - /// Will error when the decoding fails, or `OpenCV` failed to create/copy the [`Mat`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html). - /// # Safety - /// This function uses `unsafe` in order to create the [`Mat`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html). Please see [`Mat::new_rows_cols_with_data`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html#method.new_rows_cols_with_data) for more. - #[cfg(feature = "input-opencv")] - #[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-opencv")))] - pub fn decode_opencv_mat(&self) -> Result { - let mut buffer = F::write_output(self.source_frame_format, &self.buffer)?; - - let array_type = match F::Output::CHANNEL_COUNT { - 1 => CV_8UC1, - 2 => CV_8UC2, - 3 => CV_8UC3, - 4 => CV_8UC4, - _ => { - return Err(NokhwaError::ProcessFrameError { - src: self.source_frame_format, - destination: "OpenCV Mat".to_string(), - error: "Invalid Decoder FormatDecoder Channel Count".to_string(), - }) - } - }; - - unsafe { - // TODO: Look into removing this unnecessary copy. - let mat1 = Mat::new_rows_cols_with_data( - self.resolution.height_y as i32, - self.resolution.width_x as i32, - array_type, - &mut buffer as *mut std::os::raw::c_void, - Mat_AUTO_STEP, - ) - .map_err(|why| NokhwaError::ProcessFrameError { - src: self.source_frame_format, - destination: "OpenCV Mat".to_string(), - error: why.to_string(), - })?; - - Ok(mat1.clone().map_err(|why| NokhwaError::ProcessFrameError { - src: self.source_frame_format, - destination: "OpenCV Mat".to_string(), - error: why.to_string(), - })?) - } - } - - /// Decodes a image with allocation using the provided [`FormatDecoder`] into a [`Mat`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html). - /// # Errors - /// Will error when the decoding fails, or `OpenCV` failed to create/copy the [`Mat`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html). - /// # Safety - /// This function uses `unsafe` in order to create the [`Mat`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html). Please see [`Mat::new_rows_cols_with_data`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html#method.new_rows_cols_with_data) for more. - /// - /// THIS WILL CAUSE UNSOUNDNESS IF YOU USE THE MAT WHILE THE BUFFER ITSELF IS DROPPED. - #[cfg(feature = "input-opencv")] - #[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-opencv")))] - pub unsafe fn decode_as_opencv_mat(&mut self) -> Result { - let resolution = self.resolution(); - let frame_format = self.source_frame_format(); - - let array_type = match F::Output::CHANNEL_COUNT { - 1 => CV_8UC1, - 2 => CV_8UC2, - 3 => CV_8UC3, - 4 => CV_8UC4, - _ => { - return Err(NokhwaError::ProcessFrameError { - src: frame_format, - destination: "OpenCV Mat".to_string(), - error: "Invalid Decoder FormatDecoder Channel Count".to_string(), - }) - } - }; - - unsafe { - Ok(Mat::new_rows_cols_with_data( - resolution.height_y as i32, - resolution.width_x as i32, - array_type, - self.buffer_mut() as *mut std::os::raw::c_void, - Mat_AUTO_STEP, - ) - .map_err(|why| NokhwaError::ProcessFrameError { - src: frame_format, - destination: "OpenCV Mat".to_string(), - error: why.to_string(), - })?) - } - } } diff --git a/src/lib.rs b/src/lib.rs index 82543c0..9b4100f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,6 +61,64 @@ pub use threaded::CallbackCamera; pub mod utils { pub use nokhwa_core::types::*; + #[cfg(feature = "input-opencv")] + mod opencv_int { + use image::Pixel; + use nokhwa_core::{ + error::NokhwaError, + pixel_format::FormatDecoder, + types::{FrameFormat, Resolution}, + }; + use opencv::core::{Mat, Mat_AUTO_STEP, CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4}; + + /// Decodes a image with allocation using the provided [`FormatDecoder`] into a [`Mat`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html). + /// + /// Note that this does a clone when creating the buffer, to decouple the lifetime of the internal data to the temporary Buffer. If you want to avoid this, please see [`decode_as_opencv_mat`](Self::decode_as_opencv_mat). + /// # Errors + /// Will error when the decoding fails, or `OpenCV` failed to create/copy the [`Mat`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html). + /// # Safety + /// This function uses `unsafe` in order to create the [`Mat`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html). Please see [`Mat::new_rows_cols_with_data`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html#method.new_rows_cols_with_data) for more. + /// + /// Most notably, the `data` **must** stay in scope for the duration of the [`Mat`](https://docs.rs/opencv/latest/opencv/core/struct.Mat.html) or bad, ***bad*** things happen. + #[cfg(feature = "input-opencv")] + #[cfg_attr(feature = "docs-features", doc(cfg(feature = "input-opencv")))] + pub fn decode_opencv_mat( + resolution: Resolution, + data: &mut impl AsRef<[u8]>, + ) -> Result { + let array_type = match F::Output::CHANNEL_COUNT { + 1 => CV_8UC1, + 2 => CV_8UC2, + 3 => CV_8UC3, + 4 => CV_8UC4, + _ => { + return Err(NokhwaError::ProcessFrameError { + src: FrameFormat::RAWRGB, + destination: "OpenCV Mat".to_string(), + error: "Invalid Decoder FormatDecoder Channel Count".to_string(), + }) + } + }; + + unsafe { + // TODO: Look into removing this unnecessary copy. + let mat1 = Mat::new_rows_cols_with_data( + resolution.height_y as i32, + resolution.width_x as i32, + array_type, + data.as_ref().as_mut_ptr().cast(), + Mat_AUTO_STEP, + ) + .map_err(|why| NokhwaError::ProcessFrameError { + src: FrameFormat::RAWRGB, + destination: "OpenCV Mat".to_string(), + error: why.to_string(), + })?; + + Ok(mat1) + } + } + } } pub mod error {