@@ -10,13 +10,16 @@ use crate::c_api::{
1010 vx_enum, vx_df_image, vx_uint32, vx_size, vx_char,
1111 VX_SUCCESS , VX_ERROR_INVALID_REFERENCE , VX_ERROR_INVALID_PARAMETERS ,
1212 VX_ERROR_INVALID_FORMAT , VX_ERROR_NOT_IMPLEMENTED ,
13+ VX_DF_IMAGE_S16 , VX_DF_IMAGE_U16 , // Add S16/U16 format constants
1314} ;
1415use crate :: unified_c_api:: { vx_distribution, vx_remap, VxCImage } ;
1516
1617/// Image format enum for internal use
1718#[ derive( Clone , Copy , Debug , PartialEq ) ]
1819pub enum ImageFormat {
1920 Gray , // U8 - single byte per pixel
21+ GrayU16 , // U16 - two bytes per pixel
22+ GrayS16 , // S16 - two bytes per pixel (signed)
2023 GrayU32 , // U32 - four bytes per pixel (for integral image)
2124 Rgb ,
2225 Rgba ,
@@ -30,6 +33,8 @@ impl ImageFormat {
3033 pub fn channels ( & self ) -> usize {
3134 match self {
3235 ImageFormat :: Gray => 1 ,
36+ ImageFormat :: GrayU16 => 1 , // U16 is single channel, 2 bytes
37+ ImageFormat :: GrayS16 => 1 , // S16 is single channel, 2 bytes
3338 ImageFormat :: GrayU32 => 4 ,
3439 ImageFormat :: Rgb => 3 ,
3540 ImageFormat :: Rgba => 4 ,
@@ -47,6 +52,8 @@ impl ImageFormat {
4752 pub fn buffer_size ( & self , width : usize , height : usize ) -> usize {
4853 match self {
4954 ImageFormat :: Gray => width. saturating_mul ( height) ,
55+ ImageFormat :: GrayU16 => width. saturating_mul ( height) . saturating_mul ( 2 ) , // U16 = 2 bytes per pixel
56+ ImageFormat :: GrayS16 => width. saturating_mul ( height) . saturating_mul ( 2 ) , // S16 = 2 bytes per pixel
5057 ImageFormat :: GrayU32 => width. saturating_mul ( height) . saturating_mul ( 4 ) , // U32 = 4 bytes per pixel
5158 ImageFormat :: Rgb => width. saturating_mul ( height) . saturating_mul ( 3 ) ,
5259 ImageFormat :: Rgba => width. saturating_mul ( height) . saturating_mul ( 4 ) ,
@@ -147,7 +154,10 @@ impl Image {
147154fn df_image_to_format ( df : vx_df_image ) -> Option < ImageFormat > {
148155 match df {
149156 0x38303055 => Some ( ImageFormat :: Gray ) , // VX_DF_IMAGE_U8 ('U008')
150- 0x32333055 => Some ( ImageFormat :: GrayU32 ) , // VX_DF_IMAGE_U32 ('U032') - integral image output
157+ 0x31305555 => Some ( ImageFormat :: GrayU16 ) , // VX_DF_IMAGE_U16 ('U016')
158+ 0x53313053 => Some ( ImageFormat :: GrayS16 ) , // VX_DF_IMAGE_S16 ('S016') - CORRECTED
159+ 0x36313053 => Some ( ImageFormat :: GrayS16 ) , // Alternative S16 format code
160+ 0x32333055 => Some ( ImageFormat :: GrayU32 ) , // VX_DF_IMAGE_U32 ('U032')
151161 0x32424752 => Some ( ImageFormat :: Rgb ) , // VX_DF_IMAGE_RGB ('RGB2')
152162 0x41424752 => Some ( ImageFormat :: Rgba ) , // VX_DF_IMAGE_RGBA/RGBX ('RGBA')
153163 0x3231564E => Some ( ImageFormat :: NV12 ) , // VX_DF_IMAGE_NV12 ('NV12')
@@ -349,11 +359,73 @@ unsafe fn copy_rust_to_c_image_optimized(src: &Image, dst: vx_image) -> vx_statu
349359 VX_ERROR_INVALID_PARAMETERS
350360}
351361
362+ /// Copy Rust Image data back to C API image with format conversion
363+ unsafe fn convert_and_copy ( src : & Image , dst : vx_image , target_format : vx_df_image ) -> vx_status {
364+ if dst. is_null ( ) {
365+ return VX_ERROR_INVALID_REFERENCE ;
366+ }
367+
368+ // Get source and target formats
369+ let src_format = src. format ( ) ;
370+ let Some ( dst_format) = df_image_to_format ( target_format) else {
371+ return VX_ERROR_INVALID_FORMAT ;
372+ } ;
373+
374+ // If formats match, simple copy
375+ if src_format == dst_format {
376+ return copy_rust_to_c_image ( src, dst) ;
377+ }
378+
379+ // Format conversion required
380+ let img = & * ( dst as * const VxCImage ) ;
381+ let width = img. width ;
382+ let height = img. height ;
383+ let mut dst_data = match img. data . write ( ) {
384+ Ok ( d) => d,
385+ Err ( _) => return VX_ERROR_INVALID_REFERENCE ,
386+ } ;
387+
388+ eprintln ! ( "DEBUG convert_and_copy: src_format={:?}, dst_format={:?}" , src_format, dst_format) ;
389+ match ( src_format, dst_format) {
390+ ( ImageFormat :: Gray , ImageFormat :: GrayS16 ) => {
391+ // U8 (0-255) to S16 (-32768 to 32767)
392+ // U8 with offset 128 is signed: (val as i16 - 128) * 256
393+ let src_data = src. data ( ) ;
394+ let w = width as usize ;
395+ let h = height as usize ;
396+ eprintln ! ( "DEBUG convert_and_copy: converting Gray to GrayS16, {}x{}" , w, h) ;
397+ for y in 0 ..h {
398+ for x in 0 ..w {
399+ let val = src_data[ y * w + x] as i16 ;
400+ // Convert: U8(0-255) -> S16(-128 to 127) with scale factor
401+ // S16 value = (U8 - 128) * 256
402+ let s16_val = ( val - 128i16 ) . wrapping_mul ( 256i16 ) ;
403+ let idx = y * w + x;
404+ let bytes = s16_val. to_le_bytes ( ) ;
405+ if idx * 2 + 1 < dst_data. len ( ) {
406+ dst_data[ idx * 2 ] = bytes[ 0 ] ;
407+ dst_data[ idx * 2 + 1 ] = bytes[ 1 ] ;
408+ }
409+ }
410+ }
411+ VX_SUCCESS
412+ }
413+ ( src, dst) => {
414+ eprintln ! ( "DEBUG convert_and_copy: unsupported conversion {:?} -> {:?}" , src, dst) ;
415+ VX_ERROR_INVALID_FORMAT
416+ }
417+ }
418+ }
419+
352420/// Create a new Rust Image matching the C image dimensions and format
353421unsafe fn create_matching_image ( c_image : vx_image ) -> Option < Image > {
354422 let ( width, height, format) = get_image_info ( c_image) ?;
355- let format = df_image_to_format ( format) ?;
356- Image :: new ( width as usize , height as usize , format)
423+ let src_format = df_image_to_format ( format) ?;
424+ eprintln ! ( "DEBUG create_matching_image: src format={:?}" , src_format) ;
425+ // For output format, determine what we need based on context
426+ // Default to same format unless explicitly needed otherwise
427+ let output_format = src_format;
428+ Image :: new ( width as usize , height as usize , output_format)
357429}
358430
359431/// VXU Color Functions
@@ -1731,37 +1803,73 @@ pub fn vxu_sobel3x3_impl(
17311803 output_x : vx_image ,
17321804 output_y : vx_image ,
17331805) -> vx_status {
1806+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: START" ) ;
17341807 if context. is_null ( ) || input. is_null ( ) {
1808+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: null context or input" ) ;
17351809 return VX_ERROR_INVALID_REFERENCE ;
17361810 }
17371811
17381812 unsafe {
17391813 let src = match c_image_to_rust ( input) {
1740- Some ( img) => img,
1741- None => return VX_ERROR_INVALID_PARAMETERS ,
1814+ Some ( img) => {
1815+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: src format={:?}, size={}x{}" , img. format( ) , img. width( ) , img. height( ) ) ;
1816+ img
1817+ } ,
1818+ None => {
1819+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: failed to convert input" ) ;
1820+ return VX_ERROR_INVALID_PARAMETERS ;
1821+ } ,
17421822 } ;
17431823
1744- let mut gx = match create_matching_image ( output_x) {
1824+ // Check output format
1825+ let ( _, _, out_x_format) = match get_image_info ( output_x) {
1826+ Some ( info) => {
1827+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: output_x format={:#010x}" , info. 2 ) ;
1828+ info
1829+ } ,
1830+ None => {
1831+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: failed to get output_x info" ) ;
1832+ return VX_ERROR_INVALID_PARAMETERS ;
1833+ } ,
1834+ } ;
1835+
1836+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: creating temp U8 buffers" ) ;
1837+ let mut gx = match Image :: new ( src. width ( ) , src. height ( ) , ImageFormat :: Gray ) {
17451838 Some ( img) => img,
1746- None => return VX_ERROR_INVALID_PARAMETERS ,
1839+ None => {
1840+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: failed to create gx buffer" ) ;
1841+ return VX_ERROR_INVALID_PARAMETERS ;
1842+ } ,
17471843 } ;
17481844
1749- let mut gy = match create_matching_image ( output_y ) {
1845+ let mut gy = match Image :: new ( src . width ( ) , src . height ( ) , ImageFormat :: Gray ) {
17501846 Some ( img) => img,
1751- None => return VX_ERROR_INVALID_PARAMETERS ,
1847+ None => {
1848+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: failed to create gy buffer" ) ;
1849+ return VX_ERROR_INVALID_PARAMETERS ;
1850+ } ,
17521851 } ;
17531852
1853+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: calling sobel3x3 kernel" ) ;
17541854 match sobel3x3 ( & src, & mut gx, & mut gy) {
17551855 Ok ( _) => {
1756- let status_x = if output_x. is_null ( ) { VX_SUCCESS } else { copy_rust_to_c_image ( & gx, output_x) } ;
1757- let status_y = if output_y. is_null ( ) { VX_SUCCESS } else { copy_rust_to_c_image ( & gy, output_y) } ;
1856+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: kernel succeeded, converting output" ) ;
1857+ // Convert from U8 to output format
1858+ let status_x = convert_and_copy ( & gx, output_x, out_x_format) ;
1859+ let status_y = convert_and_copy ( & gy, output_y, VX_DF_IMAGE_S16 ) ;
1860+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: status_x={}, status_y={}" , status_x, status_y) ;
17581861 if status_x == VX_SUCCESS && status_y == VX_SUCCESS {
1862+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: SUCCESS" ) ;
17591863 VX_SUCCESS
17601864 } else {
1865+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: conversion failed" ) ;
17611866 VX_ERROR_INVALID_PARAMETERS
17621867 }
17631868 }
1764- Err ( _) => VX_ERROR_INVALID_PARAMETERS ,
1869+ Err ( e) => {
1870+ eprintln ! ( "DEBUG vxu_sobel3x3_impl: kernel failed: {:?}" , e) ;
1871+ VX_ERROR_INVALID_PARAMETERS
1872+ } ,
17651873 }
17661874 }
17671875}
0 commit comments