apple_vision/saliency/
mod.rs1use core::ffi::{c_char, c_void};
4use core::ptr;
5use std::ffi::CString;
6use std::path::Path;
7
8use crate::error::{from_swift, VisionError};
9use crate::ffi;
10use crate::recognize_text::BoundingBox;
11
12#[derive(Debug, Clone, PartialEq)]
14pub struct SalientRegion {
15 pub confidence: f32,
17 pub bounding_box: BoundingBox,
19}
20
21pub fn attention_saliency_in_path(
30 path: impl AsRef<Path>,
31) -> Result<Vec<SalientRegion>, VisionError> {
32 let path_str = path
33 .as_ref()
34 .to_str()
35 .ok_or_else(|| VisionError::InvalidArgument("non-UTF-8 path".into()))?;
36 let path_c = CString::new(path_str)
37 .map_err(|e| VisionError::InvalidArgument(format!("path NUL byte: {e}")))?;
38
39 let mut array: *mut c_void = ptr::null_mut();
40 let mut count: usize = 0;
41 let mut err_msg: *mut c_char = ptr::null_mut();
42
43 let status = unsafe {
45 ffi::vn_attention_saliency_in_path(path_c.as_ptr(), &mut array, &mut count, &mut err_msg)
46 };
47 if status != ffi::status::OK {
48 return Err(unsafe { from_swift(status, err_msg) });
50 }
51 if array.is_null() || count == 0 {
52 return Ok(Vec::new());
53 }
54 let typed = array.cast::<ffi::SaliencyRegionRaw>();
55 let mut out = Vec::with_capacity(count);
56 for i in 0..count {
57 let raw = unsafe { &*typed.add(i) };
59 out.push(SalientRegion {
60 confidence: raw.confidence,
61 bounding_box: BoundingBox {
62 x: raw.bbox_x,
63 y: raw.bbox_y,
64 width: raw.bbox_w,
65 height: raw.bbox_h,
66 },
67 });
68 }
69 unsafe { ffi::vn_saliency_regions_free(array, count) };
71 Ok(out)
72}