apple_vision/registration/
mod.rs1#![allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
2#![allow(clippy::too_long_first_doc_paragraph)]
3use std::ffi::{CStr, CString};
8use std::path::Path;
9use std::ptr;
10
11use crate::error::VisionError;
12use crate::ffi;
13use crate::request_base::ImageAlignmentObservation;
14
15#[derive(Debug, Clone, Copy, PartialEq)]
18pub struct TranslationalAlignment {
19 pub tx: f64,
20 pub ty: f64,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq)]
26pub struct HomographicAlignment {
27 pub matrix: [[f32; 3]; 3],
28}
29
30pub fn register_translational(
37 target: impl AsRef<Path>,
38 floating: impl AsRef<Path>,
39) -> Result<TranslationalAlignment, VisionError> {
40 let target_str = target
41 .as_ref()
42 .to_str()
43 .ok_or_else(|| VisionError::InvalidArgument("non-UTF-8 target path".into()))?;
44 let tp = CString::new(target_str)
45 .map_err(|e| VisionError::InvalidArgument(format!("target path NUL byte: {e}")))?;
46 let floating_str = floating
47 .as_ref()
48 .to_str()
49 .ok_or_else(|| VisionError::InvalidArgument("non-UTF-8 floating path".into()))?;
50 let fp = CString::new(floating_str)
51 .map_err(|e| VisionError::InvalidArgument(format!("floating path NUL byte: {e}")))?;
52 let mut out = ffi::TranslationalAlignmentRaw { tx: 0.0, ty: 0.0 };
53 let mut err: *mut std::ffi::c_char = ptr::null_mut();
54 let status = unsafe {
56 ffi::vn_register_translational_in_paths(tp.as_ptr(), fp.as_ptr(), &mut out, &mut err)
57 };
58 if status != ffi::status::OK {
59 let msg = unsafe { take_err(err) };
61 return Err(VisionError::RequestFailed(msg));
62 }
63 Ok(TranslationalAlignment {
64 tx: out.tx,
65 ty: out.ty,
66 })
67}
68
69pub fn register_translational_observation(
77 target: impl AsRef<Path>,
78 floating: impl AsRef<Path>,
79) -> Result<ImageAlignmentObservation, VisionError> {
80 register_translational(target, floating).map(ImageAlignmentObservation::translational)
81}
82
83pub fn register_homographic(
91 target: impl AsRef<Path>,
92 floating: impl AsRef<Path>,
93) -> Result<HomographicAlignment, VisionError> {
94 let target_str = target
95 .as_ref()
96 .to_str()
97 .ok_or_else(|| VisionError::InvalidArgument("non-UTF-8 target path".into()))?;
98 let tp = CString::new(target_str)
99 .map_err(|e| VisionError::InvalidArgument(format!("target path NUL byte: {e}")))?;
100 let floating_str = floating
101 .as_ref()
102 .to_str()
103 .ok_or_else(|| VisionError::InvalidArgument("non-UTF-8 floating path".into()))?;
104 let fp = CString::new(floating_str)
105 .map_err(|e| VisionError::InvalidArgument(format!("floating path NUL byte: {e}")))?;
106 let mut out = ffi::HomographicAlignmentRaw {
107 m00: 0.0,
108 m01: 0.0,
109 m02: 0.0,
110 m10: 0.0,
111 m11: 0.0,
112 m12: 0.0,
113 m20: 0.0,
114 m21: 0.0,
115 m22: 0.0,
116 _pad: 0.0,
117 };
118 let mut err: *mut std::ffi::c_char = ptr::null_mut();
119 let status = unsafe {
121 ffi::vn_register_homographic_in_paths(tp.as_ptr(), fp.as_ptr(), &mut out, &mut err)
122 };
123 if status != ffi::status::OK {
124 let msg = unsafe { take_err(err) };
126 return Err(VisionError::RequestFailed(msg));
127 }
128 Ok(HomographicAlignment {
129 matrix: [
130 [out.m00, out.m01, out.m02],
131 [out.m10, out.m11, out.m12],
132 [out.m20, out.m21, out.m22],
133 ],
134 })
135}
136
137pub fn register_homographic_observation(
145 target: impl AsRef<Path>,
146 floating: impl AsRef<Path>,
147) -> Result<ImageAlignmentObservation, VisionError> {
148 register_homographic(target, floating).map(ImageAlignmentObservation::homographic)
149}
150
151unsafe fn take_err(p: *mut std::ffi::c_char) -> String {
158 if p.is_null() {
159 return String::new();
160 }
161 let s = unsafe { CStr::from_ptr(p) }.to_string_lossy().into_owned();
163 unsafe { libc::free(p.cast()) };
165 s
166}