1use singe_cuda::memory::DeviceMemory;
2use singe_npp_sys as sys;
3
4use crate::{
5 context::StreamContext,
6 error::{Error, Result},
7 image::view::{C1, C3, ChannelLayout, ImageView},
8 try_ffi,
9 types::{BorderType, DataTypeLike, HistogramOfGradientsConfig, Point, Size},
10 utility::to_usize,
11};
12
13use super::filtering_validation::*;
14
15pub fn histogram_of_gradients_border_buffer_size(
16 config: HistogramOfGradientsConfig,
17 locations: &[Point],
18 roi: Size,
19) -> Result<usize> {
20 validate_positive_size(roi)?;
21 let location_count = i32::try_from(locations.len()).map_err(|_| Error::OutOfRange {
22 name: "location count".into(),
23 })?;
24 let mut bytes = 0;
25 unsafe {
26 try_ffi!(sys::nppiHistogramOfGradientsBorderGetBufferSize(
27 config.into(),
28 locations.as_ptr().cast(),
29 location_count,
30 roi.into(),
31 &raw mut bytes,
32 ))?;
33 }
34 to_usize(bytes, "buffer size")
35}
36
37pub fn histogram_of_gradients_border_descriptors_size(
38 config: HistogramOfGradientsConfig,
39 location_count: usize,
40) -> Result<usize> {
41 let location_count = i32::try_from(location_count).map_err(|_| Error::OutOfRange {
42 name: "location count".into(),
43 })?;
44 let mut bytes = 0;
45 unsafe {
46 try_ffi!(sys::nppiHistogramOfGradientsBorderGetDescriptorsSize(
47 config.into(),
48 location_count,
49 &raw mut bytes,
50 ))?;
51 }
52 to_usize(bytes, "descriptors size")
53}
54
55macro_rules! impl_histogram_of_gradients_border {
56 ($name:ident, $pixel_ty:ty, $layout:ty, $ffi_name:ident) => {
57 pub fn $name(
58 stream_context: &StreamContext,
59 source: &ImageView<'_, $pixel_ty, $layout>,
60 source_offset: Point,
61 locations: &[Point],
62 descriptors: &mut DeviceMemory<f32>,
63 roi: Size,
64 config: HistogramOfGradientsConfig,
65 scratch: &mut DeviceMemory<u8>,
66 border_type: BorderType,
67 ) -> Result<()> {
68 validate_border_roi(source.size(), source_offset, roi)?;
69 let descriptor_bytes =
70 histogram_of_gradients_border_descriptors_size(config, locations.len())?;
71 if descriptors.byte_len() < descriptor_bytes {
72 return Err(Error::OutOfRange {
73 name: "descriptors length".into(),
74 });
75 }
76 let scratch_bytes = histogram_of_gradients_border_buffer_size(config, locations, roi)?;
77 if scratch.len() < scratch_bytes {
78 return Err(Error::OutOfRange {
79 name: "scratch length".into(),
80 });
81 }
82 let location_count = i32::try_from(locations.len()).map_err(|_| Error::OutOfRange {
83 name: "location count".into(),
84 })?;
85 unsafe {
86 try_ffi!(sys::$ffi_name(
87 source.as_ptr().cast(),
88 source.step(),
89 source.size().into(),
90 source_offset.into(),
91 locations.as_ptr().cast(),
92 location_count,
93 descriptors.as_mut_ptr().cast(),
94 roi.into(),
95 config.into(),
96 scratch.as_mut_ptr().cast(),
97 border_type.into(),
98 stream_context.as_raw(),
99 ))?;
100 }
101 Ok(())
102 }
103 };
104}
105
106impl_histogram_of_gradients_border!(
107 histogram_of_gradients_border_u8_to_f32_c1,
108 u8,
109 C1,
110 nppiHistogramOfGradientsBorder_8u32f_C1R_Ctx
111);
112impl_histogram_of_gradients_border!(
113 histogram_of_gradients_border_u8_to_f32_c3,
114 u8,
115 C3,
116 nppiHistogramOfGradientsBorder_8u32f_C3R_Ctx
117);
118impl_histogram_of_gradients_border!(
119 histogram_of_gradients_border_u16_to_f32_c1,
120 u16,
121 C1,
122 nppiHistogramOfGradientsBorder_16u32f_C1R_Ctx
123);
124impl_histogram_of_gradients_border!(
125 histogram_of_gradients_border_u16_to_f32_c3,
126 u16,
127 C3,
128 nppiHistogramOfGradientsBorder_16u32f_C3R_Ctx
129);
130impl_histogram_of_gradients_border!(
131 histogram_of_gradients_border_i16_to_f32_c1,
132 i16,
133 C1,
134 nppiHistogramOfGradientsBorder_16s32f_C1R_Ctx
135);
136impl_histogram_of_gradients_border!(
137 histogram_of_gradients_border_i16_to_f32_c3,
138 i16,
139 C3,
140 nppiHistogramOfGradientsBorder_16s32f_C3R_Ctx
141);
142impl_histogram_of_gradients_border!(
143 histogram_of_gradients_border_f32_c1,
144 f32,
145 C1,
146 nppiHistogramOfGradientsBorder_32f_C1R_Ctx
147);
148impl_histogram_of_gradients_border!(
149 histogram_of_gradients_border_f32_c3,
150 f32,
151 C3,
152 nppiHistogramOfGradientsBorder_32f_C3R_Ctx
153);
154
155pub trait HistogramOfGradientsBorder<L: ChannelLayout>: DataTypeLike {
156 fn histogram_of_gradients_border(
157 stream_context: &StreamContext,
158 source: &ImageView<'_, Self, L>,
159 source_offset: Point,
160 locations: &[Point],
161 descriptors: &mut DeviceMemory<f32>,
162 roi: Size,
163 config: HistogramOfGradientsConfig,
164 scratch: &mut DeviceMemory<u8>,
165 border_type: BorderType,
166 ) -> Result<()>;
167}
168
169macro_rules! impl_histogram_of_gradients_border_dispatch {
170 ($pixel_ty:ty, $layout:ty, $name:ident) => {
171 impl HistogramOfGradientsBorder<$layout> for $pixel_ty {
172 fn histogram_of_gradients_border(
173 stream_context: &StreamContext,
174 source: &ImageView<'_, Self, $layout>,
175 source_offset: Point,
176 locations: &[Point],
177 descriptors: &mut DeviceMemory<f32>,
178 roi: Size,
179 config: HistogramOfGradientsConfig,
180 scratch: &mut DeviceMemory<u8>,
181 border_type: BorderType,
182 ) -> Result<()> {
183 $name(
184 stream_context,
185 source,
186 source_offset,
187 locations,
188 descriptors,
189 roi,
190 config,
191 scratch,
192 border_type,
193 )
194 }
195 }
196 };
197}
198
199impl_histogram_of_gradients_border_dispatch!(u8, C1, histogram_of_gradients_border_u8_to_f32_c1);
200impl_histogram_of_gradients_border_dispatch!(u8, C3, histogram_of_gradients_border_u8_to_f32_c3);
201impl_histogram_of_gradients_border_dispatch!(u16, C1, histogram_of_gradients_border_u16_to_f32_c1);
202impl_histogram_of_gradients_border_dispatch!(u16, C3, histogram_of_gradients_border_u16_to_f32_c3);
203impl_histogram_of_gradients_border_dispatch!(i16, C1, histogram_of_gradients_border_i16_to_f32_c1);
204impl_histogram_of_gradients_border_dispatch!(i16, C3, histogram_of_gradients_border_i16_to_f32_c3);
205impl_histogram_of_gradients_border_dispatch!(f32, C1, histogram_of_gradients_border_f32_c1);
206impl_histogram_of_gradients_border_dispatch!(f32, C3, histogram_of_gradients_border_f32_c3);
207
208pub fn histogram_of_gradients_border<T, L>(
209 stream_context: &StreamContext,
210 source: &ImageView<'_, T, L>,
211 source_offset: Point,
212 locations: &[Point],
213 descriptors: &mut DeviceMemory<f32>,
214 roi: Size,
215 config: HistogramOfGradientsConfig,
216 scratch: &mut DeviceMemory<u8>,
217 border_type: BorderType,
218) -> Result<()>
219where
220 T: HistogramOfGradientsBorder<L>,
221 L: ChannelLayout,
222{
223 T::histogram_of_gradients_border(
224 stream_context,
225 source,
226 source_offset,
227 locations,
228 descriptors,
229 roi,
230 config,
231 scratch,
232 border_type,
233 )
234}