Skip to main content

singe_npp/image/
morphology_composite.rs

1use super::*;
2
3macro_rules! impl_morph_buffer_size {
4    ($name:ident, $ffi:ident) => {
5        pub fn $name(roi: Size) -> Result<usize> {
6            validate_positive_size(roi, "roi")?;
7
8            let mut bytes = 0;
9            unsafe {
10                try_ffi!(sys::$ffi(roi.into(), &raw mut bytes))?;
11            }
12
13            to_usize(bytes, "buffer size")
14        }
15    };
16}
17
18macro_rules! impl_generic_morph_buffer_size {
19    ($trait:ident, $function:ident, $layout:ty, [$($ty:ty => $direct:ident),* $(,)?]) => {
20        pub trait $trait<Layout>: DataTypeLike + Sized {
21            fn morph_buffer_size(roi: Size) -> Result<usize>;
22        }
23
24        pub fn $function<T>(roi: Size) -> Result<usize>
25        where
26            T: $trait<$layout>,
27        {
28            T::morph_buffer_size(roi)
29        }
30
31        $(
32            impl $trait<$layout> for $ty {
33                fn morph_buffer_size(roi: Size) -> Result<usize> {
34                    $direct(roi)
35                }
36            }
37        )*
38    };
39}
40
41impl_morph_buffer_size!(morph_buffer_size_u8_c1, nppiMorphGetBufferSize_8u_C1R);
42impl_morph_buffer_size!(morph_buffer_size_u8_c3, nppiMorphGetBufferSize_8u_C3R);
43impl_morph_buffer_size!(morph_buffer_size_u8_c4, nppiMorphGetBufferSize_8u_C4R);
44impl_morph_buffer_size!(morph_buffer_size_u16_c1, nppiMorphGetBufferSize_16u_C1R);
45impl_morph_buffer_size!(morph_buffer_size_i16_c1, nppiMorphGetBufferSize_16s_C1R);
46impl_morph_buffer_size!(morph_buffer_size_f32_c1, nppiMorphGetBufferSize_32f_C1R);
47impl_morph_buffer_size!(morph_buffer_size_f32_c3, nppiMorphGetBufferSize_32f_C3R);
48impl_morph_buffer_size!(morph_buffer_size_f32_c4, nppiMorphGetBufferSize_32f_C4R);
49
50impl_generic_morph_buffer_size!(MorphBufferSizeC1, morph_buffer_size_c1, C1, [
51    u8 => morph_buffer_size_u8_c1,
52    u16 => morph_buffer_size_u16_c1,
53    i16 => morph_buffer_size_i16_c1,
54    f32 => morph_buffer_size_f32_c1,
55]);
56impl_generic_morph_buffer_size!(MorphBufferSizeC3, morph_buffer_size_c3, C3, [
57    u8 => morph_buffer_size_u8_c3,
58    f32 => morph_buffer_size_f32_c3,
59]);
60impl_generic_morph_buffer_size!(MorphBufferSizeC4, morph_buffer_size_c4, C4, [
61    u8 => morph_buffer_size_u8_c4,
62    f32 => morph_buffer_size_f32_c4,
63]);
64
65macro_rules! impl_morphology_composite_border {
66    ($with_scratch_name:ident, $name:ident, $ty:ty, $layout:ty, $buffer_size:ident, $ffi:ident) => {
67        pub fn $with_scratch_name(
68            stream_context: &StreamContext,
69            source: &ImageView<'_, $ty, $layout>,
70            source_offset: Point,
71            destination: &mut ImageViewMut<'_, $ty, $layout>,
72            mask: &[u8],
73            mask_size: Size,
74            anchor: Point,
75            scratch: &mut ScratchBuffer,
76            border_type: BorderType,
77        ) -> Result<()> {
78            validate_border_roi(source.size(), source_offset, destination.size())?;
79            validate_mask(mask, mask_size, anchor)?;
80            scratch.require($buffer_size(destination.size())?)?;
81
82            unsafe {
83                try_ffi!(sys::$ffi(
84                    source.as_ptr().cast(),
85                    source.step(),
86                    source.size().into(),
87                    source_offset.into(),
88                    destination.as_mut_ptr().cast(),
89                    destination.step(),
90                    destination.size().into(),
91                    mask.as_ptr().cast(),
92                    mask_size.into(),
93                    anchor.into(),
94                    scratch.as_mut_ptr().cast(),
95                    border_type.into(),
96                    stream_context.as_raw(),
97                ))?;
98            }
99            Ok(())
100        }
101
102        pub fn $name(
103            stream_context: &StreamContext,
104            source: &ImageView<'_, $ty, $layout>,
105            source_offset: Point,
106            destination: &mut ImageViewMut<'_, $ty, $layout>,
107            mask: &[u8],
108            mask_size: Size,
109            anchor: Point,
110            border_type: BorderType,
111        ) -> Result<()> {
112            let mut scratch = ScratchBuffer::create($buffer_size(destination.size())?)?;
113            $with_scratch_name(
114                stream_context,
115                source,
116                source_offset,
117                destination,
118                mask,
119                mask_size,
120                anchor,
121                &mut scratch,
122                border_type,
123            )
124        }
125    };
126}
127
128macro_rules! impl_generic_morphology_composite_border {
129    (
130        $trait:ident,
131        $method_with_scratch:ident,
132        $method:ident,
133        $function_with_scratch:ident,
134        $function:ident,
135        $layout:ty,
136        [$($ty:ty => $direct_with_scratch:ident, $direct:ident),* $(,)?]
137    ) => {
138        pub trait $trait<Layout>: DataTypeLike + Sized {
139            fn $method_with_scratch(
140                stream_context: &StreamContext,
141                source: &ImageView<'_, Self, Layout>,
142                source_offset: Point,
143                destination: &mut ImageViewMut<'_, Self, Layout>,
144                mask: &[u8],
145                mask_size: Size,
146                anchor: Point,
147                scratch: &mut ScratchBuffer,
148                border_type: BorderType,
149            ) -> Result<()>;
150
151            fn $method(
152                stream_context: &StreamContext,
153                source: &ImageView<'_, Self, Layout>,
154                source_offset: Point,
155                destination: &mut ImageViewMut<'_, Self, Layout>,
156                mask: &[u8],
157                mask_size: Size,
158                anchor: Point,
159                border_type: BorderType,
160            ) -> Result<()>;
161        }
162
163        pub fn $function_with_scratch<T>(
164            stream_context: &StreamContext,
165            source: &ImageView<'_, T, $layout>,
166            source_offset: Point,
167            destination: &mut ImageViewMut<'_, T, $layout>,
168            mask: &[u8],
169            mask_size: Size,
170            anchor: Point,
171            scratch: &mut ScratchBuffer,
172            border_type: BorderType,
173        ) -> Result<()>
174        where
175            T: $trait<$layout>,
176        {
177            T::$method_with_scratch(
178                stream_context,
179                source,
180                source_offset,
181                destination,
182                mask,
183                mask_size,
184                anchor,
185                scratch,
186                border_type,
187            )
188        }
189
190        pub fn $function<T>(
191            stream_context: &StreamContext,
192            source: &ImageView<'_, T, $layout>,
193            source_offset: Point,
194            destination: &mut ImageViewMut<'_, T, $layout>,
195            mask: &[u8],
196            mask_size: Size,
197            anchor: Point,
198            border_type: BorderType,
199        ) -> Result<()>
200        where
201            T: $trait<$layout>,
202        {
203            T::$method(
204                stream_context,
205                source,
206                source_offset,
207                destination,
208                mask,
209                mask_size,
210                anchor,
211                border_type,
212            )
213        }
214
215        $(
216            impl $trait<$layout> for $ty {
217                fn $method_with_scratch(
218                    stream_context: &StreamContext,
219                    source: &ImageView<'_, Self, $layout>,
220                    source_offset: Point,
221                    destination: &mut ImageViewMut<'_, Self, $layout>,
222                    mask: &[u8],
223                    mask_size: Size,
224                    anchor: Point,
225                    scratch: &mut ScratchBuffer,
226                    border_type: BorderType,
227                ) -> Result<()> {
228                    $direct_with_scratch(
229                        stream_context,
230                        source,
231                        source_offset,
232                        destination,
233                        mask,
234                        mask_size,
235                        anchor,
236                        scratch,
237                        border_type,
238                    )
239                }
240
241                fn $method(
242                    stream_context: &StreamContext,
243                    source: &ImageView<'_, Self, $layout>,
244                    source_offset: Point,
245                    destination: &mut ImageViewMut<'_, Self, $layout>,
246                    mask: &[u8],
247                    mask_size: Size,
248                    anchor: Point,
249                    border_type: BorderType,
250                ) -> Result<()> {
251                    $direct(
252                        stream_context,
253                        source,
254                        source_offset,
255                        destination,
256                        mask,
257                        mask_size,
258                        anchor,
259                        border_type,
260                    )
261                }
262            }
263        )*
264    };
265}
266
267impl_morphology_composite_border!(
268    morph_close_border_u8_c1_with_scratch,
269    morph_close_border_u8_c1,
270    u8,
271    C1,
272    morph_buffer_size_u8_c1,
273    nppiMorphCloseBorder_8u_C1R_Ctx
274);
275impl_morphology_composite_border!(
276    morph_close_border_u8_c3_with_scratch,
277    morph_close_border_u8_c3,
278    u8,
279    C3,
280    morph_buffer_size_u8_c3,
281    nppiMorphCloseBorder_8u_C3R_Ctx
282);
283impl_morphology_composite_border!(
284    morph_close_border_u8_c4_with_scratch,
285    morph_close_border_u8_c4,
286    u8,
287    C4,
288    morph_buffer_size_u8_c4,
289    nppiMorphCloseBorder_8u_C4R_Ctx
290);
291impl_morphology_composite_border!(
292    morph_close_border_u16_c1_with_scratch,
293    morph_close_border_u16_c1,
294    u16,
295    C1,
296    morph_buffer_size_u16_c1,
297    nppiMorphCloseBorder_16u_C1R_Ctx
298);
299impl_morphology_composite_border!(
300    morph_close_border_i16_c1_with_scratch,
301    morph_close_border_i16_c1,
302    i16,
303    C1,
304    morph_buffer_size_i16_c1,
305    nppiMorphCloseBorder_16s_C1R_Ctx
306);
307impl_morphology_composite_border!(
308    morph_close_border_f32_c1_with_scratch,
309    morph_close_border_f32_c1,
310    f32,
311    C1,
312    morph_buffer_size_f32_c1,
313    nppiMorphCloseBorder_32f_C1R_Ctx
314);
315impl_morphology_composite_border!(
316    morph_close_border_f32_c3_with_scratch,
317    morph_close_border_f32_c3,
318    f32,
319    C3,
320    morph_buffer_size_f32_c3,
321    nppiMorphCloseBorder_32f_C3R_Ctx
322);
323impl_morphology_composite_border!(
324    morph_close_border_f32_c4_with_scratch,
325    morph_close_border_f32_c4,
326    f32,
327    C4,
328    morph_buffer_size_f32_c4,
329    nppiMorphCloseBorder_32f_C4R_Ctx
330);
331
332impl_morphology_composite_border!(
333    morph_open_border_u8_c1_with_scratch,
334    morph_open_border_u8_c1,
335    u8,
336    C1,
337    morph_buffer_size_u8_c1,
338    nppiMorphOpenBorder_8u_C1R_Ctx
339);
340impl_morphology_composite_border!(
341    morph_open_border_u8_c3_with_scratch,
342    morph_open_border_u8_c3,
343    u8,
344    C3,
345    morph_buffer_size_u8_c3,
346    nppiMorphOpenBorder_8u_C3R_Ctx
347);
348impl_morphology_composite_border!(
349    morph_open_border_u8_c4_with_scratch,
350    morph_open_border_u8_c4,
351    u8,
352    C4,
353    morph_buffer_size_u8_c4,
354    nppiMorphOpenBorder_8u_C4R_Ctx
355);
356impl_morphology_composite_border!(
357    morph_open_border_u16_c1_with_scratch,
358    morph_open_border_u16_c1,
359    u16,
360    C1,
361    morph_buffer_size_u16_c1,
362    nppiMorphOpenBorder_16u_C1R_Ctx
363);
364impl_morphology_composite_border!(
365    morph_open_border_i16_c1_with_scratch,
366    morph_open_border_i16_c1,
367    i16,
368    C1,
369    morph_buffer_size_i16_c1,
370    nppiMorphOpenBorder_16s_C1R_Ctx
371);
372impl_morphology_composite_border!(
373    morph_open_border_f32_c1_with_scratch,
374    morph_open_border_f32_c1,
375    f32,
376    C1,
377    morph_buffer_size_f32_c1,
378    nppiMorphOpenBorder_32f_C1R_Ctx
379);
380impl_morphology_composite_border!(
381    morph_open_border_f32_c3_with_scratch,
382    morph_open_border_f32_c3,
383    f32,
384    C3,
385    morph_buffer_size_f32_c3,
386    nppiMorphOpenBorder_32f_C3R_Ctx
387);
388impl_morphology_composite_border!(
389    morph_open_border_f32_c4_with_scratch,
390    morph_open_border_f32_c4,
391    f32,
392    C4,
393    morph_buffer_size_f32_c4,
394    nppiMorphOpenBorder_32f_C4R_Ctx
395);
396
397impl_morphology_composite_border!(
398    morph_top_hat_border_u8_c1_with_scratch,
399    morph_top_hat_border_u8_c1,
400    u8,
401    C1,
402    morph_buffer_size_u8_c1,
403    nppiMorphTopHatBorder_8u_C1R_Ctx
404);
405impl_morphology_composite_border!(
406    morph_top_hat_border_u8_c3_with_scratch,
407    morph_top_hat_border_u8_c3,
408    u8,
409    C3,
410    morph_buffer_size_u8_c3,
411    nppiMorphTopHatBorder_8u_C3R_Ctx
412);
413impl_morphology_composite_border!(
414    morph_top_hat_border_u8_c4_with_scratch,
415    morph_top_hat_border_u8_c4,
416    u8,
417    C4,
418    morph_buffer_size_u8_c4,
419    nppiMorphTopHatBorder_8u_C4R_Ctx
420);
421impl_morphology_composite_border!(
422    morph_top_hat_border_u16_c1_with_scratch,
423    morph_top_hat_border_u16_c1,
424    u16,
425    C1,
426    morph_buffer_size_u16_c1,
427    nppiMorphTopHatBorder_16u_C1R_Ctx
428);
429impl_morphology_composite_border!(
430    morph_top_hat_border_i16_c1_with_scratch,
431    morph_top_hat_border_i16_c1,
432    i16,
433    C1,
434    morph_buffer_size_i16_c1,
435    nppiMorphTopHatBorder_16s_C1R_Ctx
436);
437impl_morphology_composite_border!(
438    morph_top_hat_border_f32_c1_with_scratch,
439    morph_top_hat_border_f32_c1,
440    f32,
441    C1,
442    morph_buffer_size_f32_c1,
443    nppiMorphTopHatBorder_32f_C1R_Ctx
444);
445impl_morphology_composite_border!(
446    morph_top_hat_border_f32_c3_with_scratch,
447    morph_top_hat_border_f32_c3,
448    f32,
449    C3,
450    morph_buffer_size_f32_c3,
451    nppiMorphTopHatBorder_32f_C3R_Ctx
452);
453impl_morphology_composite_border!(
454    morph_top_hat_border_f32_c4_with_scratch,
455    morph_top_hat_border_f32_c4,
456    f32,
457    C4,
458    morph_buffer_size_f32_c4,
459    nppiMorphTopHatBorder_32f_C4R_Ctx
460);
461
462impl_morphology_composite_border!(
463    morph_black_hat_border_u8_c1_with_scratch,
464    morph_black_hat_border_u8_c1,
465    u8,
466    C1,
467    morph_buffer_size_u8_c1,
468    nppiMorphBlackHatBorder_8u_C1R_Ctx
469);
470impl_morphology_composite_border!(
471    morph_black_hat_border_u8_c3_with_scratch,
472    morph_black_hat_border_u8_c3,
473    u8,
474    C3,
475    morph_buffer_size_u8_c3,
476    nppiMorphBlackHatBorder_8u_C3R_Ctx
477);
478impl_morphology_composite_border!(
479    morph_black_hat_border_u8_c4_with_scratch,
480    morph_black_hat_border_u8_c4,
481    u8,
482    C4,
483    morph_buffer_size_u8_c4,
484    nppiMorphBlackHatBorder_8u_C4R_Ctx
485);
486impl_morphology_composite_border!(
487    morph_black_hat_border_u16_c1_with_scratch,
488    morph_black_hat_border_u16_c1,
489    u16,
490    C1,
491    morph_buffer_size_u16_c1,
492    nppiMorphBlackHatBorder_16u_C1R_Ctx
493);
494impl_morphology_composite_border!(
495    morph_black_hat_border_i16_c1_with_scratch,
496    morph_black_hat_border_i16_c1,
497    i16,
498    C1,
499    morph_buffer_size_i16_c1,
500    nppiMorphBlackHatBorder_16s_C1R_Ctx
501);
502impl_morphology_composite_border!(
503    morph_black_hat_border_f32_c1_with_scratch,
504    morph_black_hat_border_f32_c1,
505    f32,
506    C1,
507    morph_buffer_size_f32_c1,
508    nppiMorphBlackHatBorder_32f_C1R_Ctx
509);
510impl_morphology_composite_border!(
511    morph_black_hat_border_f32_c3_with_scratch,
512    morph_black_hat_border_f32_c3,
513    f32,
514    C3,
515    morph_buffer_size_f32_c3,
516    nppiMorphBlackHatBorder_32f_C3R_Ctx
517);
518impl_morphology_composite_border!(
519    morph_black_hat_border_f32_c4_with_scratch,
520    morph_black_hat_border_f32_c4,
521    f32,
522    C4,
523    morph_buffer_size_f32_c4,
524    nppiMorphBlackHatBorder_32f_C4R_Ctx
525);
526
527impl_morphology_composite_border!(
528    morph_gradient_border_u8_c1_with_scratch,
529    morph_gradient_border_u8_c1,
530    u8,
531    C1,
532    morph_buffer_size_u8_c1,
533    nppiMorphGradientBorder_8u_C1R_Ctx
534);
535impl_morphology_composite_border!(
536    morph_gradient_border_u8_c3_with_scratch,
537    morph_gradient_border_u8_c3,
538    u8,
539    C3,
540    morph_buffer_size_u8_c3,
541    nppiMorphGradientBorder_8u_C3R_Ctx
542);
543impl_morphology_composite_border!(
544    morph_gradient_border_u8_c4_with_scratch,
545    morph_gradient_border_u8_c4,
546    u8,
547    C4,
548    morph_buffer_size_u8_c4,
549    nppiMorphGradientBorder_8u_C4R_Ctx
550);
551impl_morphology_composite_border!(
552    morph_gradient_border_u16_c1_with_scratch,
553    morph_gradient_border_u16_c1,
554    u16,
555    C1,
556    morph_buffer_size_u16_c1,
557    nppiMorphGradientBorder_16u_C1R_Ctx
558);
559impl_morphology_composite_border!(
560    morph_gradient_border_i16_c1_with_scratch,
561    morph_gradient_border_i16_c1,
562    i16,
563    C1,
564    morph_buffer_size_i16_c1,
565    nppiMorphGradientBorder_16s_C1R_Ctx
566);
567impl_morphology_composite_border!(
568    morph_gradient_border_f32_c1_with_scratch,
569    morph_gradient_border_f32_c1,
570    f32,
571    C1,
572    morph_buffer_size_f32_c1,
573    nppiMorphGradientBorder_32f_C1R_Ctx
574);
575impl_morphology_composite_border!(
576    morph_gradient_border_f32_c3_with_scratch,
577    morph_gradient_border_f32_c3,
578    f32,
579    C3,
580    morph_buffer_size_f32_c3,
581    nppiMorphGradientBorder_32f_C3R_Ctx
582);
583impl_morphology_composite_border!(
584    morph_gradient_border_f32_c4_with_scratch,
585    morph_gradient_border_f32_c4,
586    f32,
587    C4,
588    morph_buffer_size_f32_c4,
589    nppiMorphGradientBorder_32f_C4R_Ctx
590);
591
592impl_generic_morphology_composite_border!(
593    MorphCloseBorderC1,
594    morph_close_border_with_scratch,
595    morph_close_border,
596    morph_close_border_c1_with_scratch,
597    morph_close_border_c1,
598    C1,
599    [
600        u8 => morph_close_border_u8_c1_with_scratch, morph_close_border_u8_c1,
601        u16 => morph_close_border_u16_c1_with_scratch, morph_close_border_u16_c1,
602        i16 => morph_close_border_i16_c1_with_scratch, morph_close_border_i16_c1,
603        f32 => morph_close_border_f32_c1_with_scratch, morph_close_border_f32_c1,
604    ]
605);
606impl_generic_morphology_composite_border!(
607    MorphCloseBorderC3,
608    morph_close_border_with_scratch,
609    morph_close_border,
610    morph_close_border_c3_with_scratch,
611    morph_close_border_c3,
612    C3,
613    [
614        u8 => morph_close_border_u8_c3_with_scratch, morph_close_border_u8_c3,
615        f32 => morph_close_border_f32_c3_with_scratch, morph_close_border_f32_c3,
616    ]
617);
618impl_generic_morphology_composite_border!(
619    MorphCloseBorderC4,
620    morph_close_border_with_scratch,
621    morph_close_border,
622    morph_close_border_c4_with_scratch,
623    morph_close_border_c4,
624    C4,
625    [
626        u8 => morph_close_border_u8_c4_with_scratch, morph_close_border_u8_c4,
627        f32 => morph_close_border_f32_c4_with_scratch, morph_close_border_f32_c4,
628    ]
629);
630impl_generic_morphology_composite_border!(
631    MorphOpenBorderC1,
632    morph_open_border_with_scratch,
633    morph_open_border,
634    morph_open_border_c1_with_scratch,
635    morph_open_border_c1,
636    C1,
637    [
638        u8 => morph_open_border_u8_c1_with_scratch, morph_open_border_u8_c1,
639        u16 => morph_open_border_u16_c1_with_scratch, morph_open_border_u16_c1,
640        i16 => morph_open_border_i16_c1_with_scratch, morph_open_border_i16_c1,
641        f32 => morph_open_border_f32_c1_with_scratch, morph_open_border_f32_c1,
642    ]
643);
644impl_generic_morphology_composite_border!(
645    MorphOpenBorderC3,
646    morph_open_border_with_scratch,
647    morph_open_border,
648    morph_open_border_c3_with_scratch,
649    morph_open_border_c3,
650    C3,
651    [
652        u8 => morph_open_border_u8_c3_with_scratch, morph_open_border_u8_c3,
653        f32 => morph_open_border_f32_c3_with_scratch, morph_open_border_f32_c3,
654    ]
655);
656impl_generic_morphology_composite_border!(
657    MorphOpenBorderC4,
658    morph_open_border_with_scratch,
659    morph_open_border,
660    morph_open_border_c4_with_scratch,
661    morph_open_border_c4,
662    C4,
663    [
664        u8 => morph_open_border_u8_c4_with_scratch, morph_open_border_u8_c4,
665        f32 => morph_open_border_f32_c4_with_scratch, morph_open_border_f32_c4,
666    ]
667);
668impl_generic_morphology_composite_border!(
669    MorphTopHatBorderC1,
670    morph_top_hat_border_with_scratch,
671    morph_top_hat_border,
672    morph_top_hat_border_c1_with_scratch,
673    morph_top_hat_border_c1,
674    C1,
675    [
676        u8 => morph_top_hat_border_u8_c1_with_scratch, morph_top_hat_border_u8_c1,
677        u16 => morph_top_hat_border_u16_c1_with_scratch, morph_top_hat_border_u16_c1,
678        i16 => morph_top_hat_border_i16_c1_with_scratch, morph_top_hat_border_i16_c1,
679        f32 => morph_top_hat_border_f32_c1_with_scratch, morph_top_hat_border_f32_c1,
680    ]
681);
682impl_generic_morphology_composite_border!(
683    MorphTopHatBorderC3,
684    morph_top_hat_border_with_scratch,
685    morph_top_hat_border,
686    morph_top_hat_border_c3_with_scratch,
687    morph_top_hat_border_c3,
688    C3,
689    [
690        u8 => morph_top_hat_border_u8_c3_with_scratch, morph_top_hat_border_u8_c3,
691        f32 => morph_top_hat_border_f32_c3_with_scratch, morph_top_hat_border_f32_c3,
692    ]
693);
694impl_generic_morphology_composite_border!(
695    MorphTopHatBorderC4,
696    morph_top_hat_border_with_scratch,
697    morph_top_hat_border,
698    morph_top_hat_border_c4_with_scratch,
699    morph_top_hat_border_c4,
700    C4,
701    [
702        u8 => morph_top_hat_border_u8_c4_with_scratch, morph_top_hat_border_u8_c4,
703        f32 => morph_top_hat_border_f32_c4_with_scratch, morph_top_hat_border_f32_c4,
704    ]
705);
706impl_generic_morphology_composite_border!(
707    MorphBlackHatBorderC1,
708    morph_black_hat_border_with_scratch,
709    morph_black_hat_border,
710    morph_black_hat_border_c1_with_scratch,
711    morph_black_hat_border_c1,
712    C1,
713    [
714        u8 => morph_black_hat_border_u8_c1_with_scratch, morph_black_hat_border_u8_c1,
715        u16 => morph_black_hat_border_u16_c1_with_scratch, morph_black_hat_border_u16_c1,
716        i16 => morph_black_hat_border_i16_c1_with_scratch, morph_black_hat_border_i16_c1,
717        f32 => morph_black_hat_border_f32_c1_with_scratch, morph_black_hat_border_f32_c1,
718    ]
719);
720impl_generic_morphology_composite_border!(
721    MorphBlackHatBorderC3,
722    morph_black_hat_border_with_scratch,
723    morph_black_hat_border,
724    morph_black_hat_border_c3_with_scratch,
725    morph_black_hat_border_c3,
726    C3,
727    [
728        u8 => morph_black_hat_border_u8_c3_with_scratch, morph_black_hat_border_u8_c3,
729        f32 => morph_black_hat_border_f32_c3_with_scratch, morph_black_hat_border_f32_c3,
730    ]
731);
732impl_generic_morphology_composite_border!(
733    MorphBlackHatBorderC4,
734    morph_black_hat_border_with_scratch,
735    morph_black_hat_border,
736    morph_black_hat_border_c4_with_scratch,
737    morph_black_hat_border_c4,
738    C4,
739    [
740        u8 => morph_black_hat_border_u8_c4_with_scratch, morph_black_hat_border_u8_c4,
741        f32 => morph_black_hat_border_f32_c4_with_scratch, morph_black_hat_border_f32_c4,
742    ]
743);
744impl_generic_morphology_composite_border!(
745    MorphGradientBorderC1,
746    morph_gradient_border_with_scratch,
747    morph_gradient_border,
748    morph_gradient_border_c1_with_scratch,
749    morph_gradient_border_c1,
750    C1,
751    [
752        u8 => morph_gradient_border_u8_c1_with_scratch, morph_gradient_border_u8_c1,
753        u16 => morph_gradient_border_u16_c1_with_scratch, morph_gradient_border_u16_c1,
754        i16 => morph_gradient_border_i16_c1_with_scratch, morph_gradient_border_i16_c1,
755        f32 => morph_gradient_border_f32_c1_with_scratch, morph_gradient_border_f32_c1,
756    ]
757);
758impl_generic_morphology_composite_border!(
759    MorphGradientBorderC3,
760    morph_gradient_border_with_scratch,
761    morph_gradient_border,
762    morph_gradient_border_c3_with_scratch,
763    morph_gradient_border_c3,
764    C3,
765    [
766        u8 => morph_gradient_border_u8_c3_with_scratch, morph_gradient_border_u8_c3,
767        f32 => morph_gradient_border_f32_c3_with_scratch, morph_gradient_border_f32_c3,
768    ]
769);
770impl_generic_morphology_composite_border!(
771    MorphGradientBorderC4,
772    morph_gradient_border_with_scratch,
773    morph_gradient_border,
774    morph_gradient_border_c4_with_scratch,
775    morph_gradient_border_c4,
776    C4,
777    [
778        u8 => morph_gradient_border_u8_c4_with_scratch, morph_gradient_border_u8_c4,
779        f32 => morph_gradient_border_f32_c4_with_scratch, morph_gradient_border_f32_c4,
780    ]
781);