Skip to main content

bayer/
ffi.rs

1//! Foreign function interface.
2
3use std::io::{Cursor,Read};
4use std::mem;
5use std::ptr;
6use std::slice;
7use libc::{c_uchar,c_uint,size_t};
8
9use ::{BayerDepth,BayerError,BayerResult,CFA,RasterDepth,RasterMut};
10use demosaic;
11
12/// Dummy opaque structure, equivalent to RasterMut<'a>.
13pub struct CRasterMut;
14
15// Print with "file:line - " prefix, for more informative error messages.
16macro_rules! printerrorln {
17    ($e:expr) => {{
18        println!("{}:{} - {}", file!(), line!(), $e);
19    }};
20    ($fmt:expr, $arg:tt) => {{
21        print!("{}:{} - ", file!(), line!());
22        println!($fmt, $arg);
23    }};
24}
25
26unsafe fn transmute_raster_mut<'a>(dst: *mut CRasterMut)
27        -> &'a mut RasterMut<'a> {
28    let ptr: *mut RasterMut = mem::transmute(dst);
29    &mut *ptr
30}
31
32fn run_demosaic<F>(file: &'static str, line: u32,
33        run: F,
34        src: *const c_uchar, src_len: size_t,
35        depth: c_uint, be: c_uint, cfa: c_uint,
36        dst: *mut CRasterMut)
37        -> c_uint
38        where F: FnOnce(&mut Read, BayerDepth, CFA, &mut RasterMut) -> BayerResult<()> {
39    if src.is_null() || dst.is_null() {
40        println!("{} {} - bad input parameters", file, line);
41        return 1;
42    }
43
44    let depth = match (depth, be) {
45        (8, _) => BayerDepth::Depth8,
46        (16, 0) => BayerDepth::Depth16LE,
47        (16, _) => BayerDepth::Depth16BE,
48        _ => {
49            println!("{} {} - invalid depth", file, line);
50            return 2;
51        }
52    };
53
54    let cfa = match cfa {
55        0 => CFA::BGGR,
56        1 => CFA::GBRG,
57        2 => CFA::GRBG,
58        3 => CFA::RGGB,
59        _ => {
60            println!("{} {} - invalid cfa", file, line);
61            return 1;
62        }
63    };
64
65    let src_slice = unsafe{ slice::from_raw_parts(src, src_len) };
66    let dst_raster = unsafe{ transmute_raster_mut(dst) };
67
68    match run(&mut Cursor::new(&src_slice[..]), depth, cfa, dst_raster) {
69        Ok(_) => 0,
70        Err(BayerError::WrongResolution) => 2,
71        Err(BayerError::WrongDepth) => 3,
72        Err(_) => 1,
73    }
74}
75
76/*--------------------------------------------------------------*/
77/* Demosaicing algorithms                                       */
78/*--------------------------------------------------------------*/
79
80/// Demosaicing without any interpolation.
81#[no_mangle]
82pub extern "C" fn bayerrs_demosaic_none(
83        src: *const c_uchar, src_len: size_t,
84        depth: c_uint, be: c_uint, cfa: c_uint,
85        dst: *mut CRasterMut)
86        -> c_uint {
87    run_demosaic(file!(), line!(),
88            demosaic::none::run,
89            src, src_len, depth, be, cfa, dst)
90}
91
92/// Demosaicing using nearest neighbour interpolation.
93#[no_mangle]
94pub extern "C" fn bayerrs_demosaic_nearest_neighbour(
95        src: *const c_uchar, src_len: size_t,
96        depth: c_uint, be: c_uint, cfa: c_uint,
97        dst: *mut CRasterMut)
98        -> c_uint {
99    run_demosaic(file!(), line!(),
100            demosaic::nearestneighbour::run,
101            src, src_len, depth, be, cfa, dst)
102}
103
104/// Demosaicing using linear interpolation.
105#[no_mangle]
106pub extern "C" fn bayerrs_demosaic_linear(
107        src: *const c_uchar, src_len: size_t,
108        depth: c_uint, be: c_uint, cfa: c_uint,
109        dst: *mut CRasterMut)
110        -> c_uint {
111    run_demosaic(file!(), line!(),
112            demosaic::linear::run,
113            src, src_len, depth, be, cfa, dst)
114}
115
116/// Demosaicing using cubic interpolation.
117#[no_mangle]
118pub extern "C" fn bayerrs_demosaic_cubic(
119        src: *const c_uchar, src_len: size_t,
120        depth: c_uint, be: c_uint, cfa: c_uint,
121        dst: *mut CRasterMut)
122        -> c_uint {
123    run_demosaic(file!(), line!(),
124            demosaic::cubic::run,
125            src, src_len, depth, be, cfa, dst)
126}
127
128/*--------------------------------------------------------------*/
129/* Raster                                                       */
130/*--------------------------------------------------------------*/
131
132/// Allocate a new raster.
133#[no_mangle]
134pub extern "C" fn bayerrs_raster_mut_alloc(
135        x: size_t, y: size_t, w: size_t, h: size_t, stride: size_t, depth: c_uint,
136        buf: *mut c_uchar, buf_len: size_t)
137        -> *mut CRasterMut {
138    if buf.is_null() {
139        printerrorln!("bad input parameters");
140        return ptr::null_mut();
141    }
142
143    let depth = match depth {
144        8 => RasterDepth::Depth8,
145        16 => RasterDepth::Depth16,
146        _ => {
147            printerrorln!("bad input parameters");
148            return ptr::null_mut();
149        }
150    };
151
152    let buf_slice = unsafe{ slice::from_raw_parts_mut(buf, buf_len) };
153    let raster = RasterMut::with_offset(x, y, w, h, stride, depth, buf_slice);
154    let rptr = Box::into_raw(Box::new(raster));
155    let cptr: *mut CRasterMut = unsafe{ mem::transmute(rptr) };
156    cptr
157}
158
159/// Free a previously allocated raster.
160#[no_mangle]
161pub extern "C" fn bayerrs_raster_mut_free(raster: *mut CRasterMut) {
162    if raster.is_null() {
163        return;
164    }
165
166    let rptr: *mut RasterMut = unsafe{ mem::transmute(raster) };
167    let _raster = unsafe{ Box::from_raw(rptr) };
168}