use std::ffi::c_void;
#[repr(C)]
pub struct SDLPixelFormat {
data: c_void,
}
#[repr(C)]
pub struct SDLRect {
x: i16,
y: i16,
w: u16,
h: u16,
}
#[repr(C)]
pub struct SDLSurface {
flags: u32,
format: *const SDLPixelFormat,
w: i32,
h: i32,
pitch: i32,
pixels: *mut c_void,
userdata: *mut c_void,
locked: i32,
lock_data: *mut c_void,
clip_rect: SDLRect,
map: *mut c_void,
refcount: i32,
}
#[link(name = "SDL")]
extern{
#[link_name = "SDL_MapRGBA"]
fn c_sdl_map_rgba(format: *const SDLPixelFormat, r: u8, g: u8, b: u8, a: u8) -> u32;
#[link_name = "SDL_CreateRGBSurface"]
fn c_sdl_create_rgb_surface(flags: u32, width: u32, height: u32, depth: u32, r_mask: u32, g_mask: u32, b_mask: u32, a_mask: u32) -> *mut SDLSurface;
}
fn map_rgba(format: &SDLPixelFormat, r: u8, g: u8, b: u8, a: u8) -> u32 {
unsafe {
c_sdl_map_rgba(format as *const SDLPixelFormat, r, g, b, a)
}
}
#[no_mangle]
pub extern "C" fn render_tensor(data: *const u8, width: u32, height: u32, channels: i32) -> *mut SDLSurface {
let surface = unsafe {
c_sdl_create_rgb_surface(0, width, height, 32, 0xff, 0xff00, 0xff0000, 0xff000000)
};
println!("surface: {:?}, pixels: {:?}, w: {}, h: {}", surface, unsafe { (*surface).pixels }, unsafe { (*surface).w }, unsafe { (*surface).h });
let width = width as usize;
let height = height as usize;
let channels = channels as usize;
let pitch = unsafe {
(*surface).pitch as usize / 4
};
let data = unsafe {
std::slice::from_raw_parts(data, width * height * channels)
};
let pixels: &mut [u32] = unsafe {
std::slice::from_raw_parts_mut((*surface).pixels.cast(), height * pitch)
};
let format = unsafe {
(*surface).format.as_ref().unwrap()
};
for y in 0 .. height {
let data_rowstart = y * width * (channels as usize);
let pixels_rowstart = y * pitch;
for x in 0 .. width {
let data_pixstart = data_rowstart + x * channels;
let (red, green, blue, alpha) = match channels {
1 => {
let grey = data[data_pixstart];
(grey, grey, grey, 255)
}
3 => {
let red = data[data_pixstart];
let green = data[data_pixstart + 1];
let blue = data[data_pixstart + 2];
(red, green, blue, 255)
}
4 => {
let red = data[data_pixstart];
let green = data[data_pixstart + 1];
let blue = data[data_pixstart + 2];
let alpha = data[data_pixstart + 3];
(red, green, blue, alpha)
}
_ => panic!("We only handle 1, 3, and 4 channels!")
};
let color_value = map_rgba(format, red, green, blue, alpha);
pixels[pixels_rowstart + x] = color_value;
}
}
println!("Surface = {:?}, pixels = {:?}", surface, unsafe { (*surface).pixels });
surface
}