Skip to content

Commit a11744f

Browse files
committed
graphics module
* wrapper for graphics API from arrayfire * Fix in image::{medfilt, minfilt, maxfilt} API * Modified ColorMap enum to use C representation * Corrections to examples to reflect new changes * Graphics examples: snow(noise), histogram
1 parent 0a64db6 commit a11744f

File tree

11 files changed

+306
-9
lines changed

11 files changed

+306
-9
lines changed

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,11 @@ path = "examples/helloworld.rs"
2323
[[example]]
2424
name = "pi"
2525
path = "examples/pi.rs"
26+
27+
[[example]]
28+
name = "snow"
29+
path = "examples/snow.rs"
30+
31+
[[example]]
32+
name = "histogram"
33+
path = "examples/histogram.rs"

build.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"build_cpu": "ON",
1313
"build_examples": "OFF",
1414
"build_test": "OFF",
15-
"build_graphics": "OFF",
15+
"build_graphics": "ON",
1616

1717
"glew_static": "OFF",
1818
"freeimage_type": "DYNAMIC",

examples/histogram.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
extern crate arrayfire as af;
2+
3+
use af::Window;
4+
use std::env;
5+
use std::path::PathBuf;
6+
7+
#[allow(unused_variables)]
8+
#[allow(unused_must_use)]
9+
fn main() {
10+
af::set_device(0);
11+
af::info();
12+
13+
let assets_dir = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap())
14+
.join("arrayfire").join("assets").join("examples").join("images");
15+
16+
let img_wnd = match Window::new(480, 640, String::from("Input Image")) {
17+
Ok(v) => { v.set_position(100, 100).unwrap(); v },
18+
Err(e)=> panic!("Window creation failed, exiting: {:?}", e),
19+
};
20+
21+
let hst_wnd = match Window::new(512, 512, String::from("Input Image Histogram")) {
22+
Ok(v) => { v.set_position(600, 100).unwrap(); v },
23+
Err(e)=> panic!("Window creation failed, exiting: {:?}", e),
24+
};
25+
26+
let (man, hst) = match af::load_image(format!("{}/man.jpg", assets_dir.display()), false) {
27+
Ok(v) => match af::histogram(&v, 256, 0.0, 255.0) {
28+
Ok(h) => (v, h),
29+
Err(e)=> panic!("Histogram computation failed, exiting: {:?}", e),
30+
},
31+
Err(e)=> panic!("Image loading failed, exiting: {:?}", e),
32+
};
33+
34+
let disp_img = man.dims()
35+
.and_then(|x| af::constant(255 as f32, x))
36+
.and_then(|x| af::div(&man, &x))
37+
.unwrap();
38+
39+
loop {
40+
img_wnd.draw_image(&disp_img, None);
41+
hst_wnd.draw_hist(&hst, 0.0, 255.0, None);
42+
43+
if img_wnd.is_closed().unwrap() == true { break; }
44+
if hst_wnd.is_closed().unwrap() == true { break; }
45+
}
46+
}

examples/pi.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ fn main() {
1919
let start = PreciseTime::now();
2020

2121
for bench_iter in 0..100 {
22-
let pi_val = af::add(&(x*x), &(y*y))
22+
let pi_val = af::add(x*x, y*y)
2323
.and_then( |z| af::sqrt(&z) )
24-
.and_then( |z| af::le(&z, &af::constant(1, dims).unwrap()) )
24+
.and_then( |z| af::le(z, af::constant(1, dims).unwrap()) )
2525
.and_then( |z| af::sum_all(&z) )
2626
.map( |z| z.0 * 4.0/(samples as f64) )
2727
.unwrap();

examples/snow.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
extern crate arrayfire as af;
2+
3+
use af::Dim4;
4+
use af::Window;
5+
6+
#[allow(unused_variables)]
7+
#[allow(unused_must_use)]
8+
fn main() {
9+
af::set_device(0);
10+
af::info();
11+
12+
let wnd = match Window::new(1280, 720, String::from("Snow")) {
13+
Ok(v) => v,
14+
Err(e)=> panic!("Window creation failed, exiting"),
15+
};
16+
17+
let dims = Dim4::new(&[1280, 720, 3, 1]);
18+
19+
loop {
20+
af::randu(dims, af::Aftype::F32).as_ref()
21+
.map(|arr| wnd.draw_image(arr, None));
22+
23+
if wnd.is_closed().unwrap() == true { break; }
24+
}
25+
}

src/arith/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ macro_rules! convertable_type_def {
207207
)
208208
}
209209

210+
convertable_type_def!(u64);
211+
convertable_type_def!(i64);
210212
convertable_type_def!(f64);
211213
convertable_type_def!(f32);
212214
convertable_type_def!(i32);

src/defines.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,15 @@ pub enum NormType {
168168
MATRIX_2 = 6,
169169
MATRIX_L_PQ = 7,
170170
}
171+
172+
#[repr(C)]
173+
#[derive(Copy, Clone)]
174+
pub enum ColorMap {
175+
DEFAULT = 0,
176+
SPECTRUM= 1,
177+
COLORS = 2,
178+
RED = 3,
179+
MOOD = 4,
180+
HEAT = 5,
181+
BLUE = 6,
182+
}

src/graphics.rs

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
extern crate libc;
2+
3+
use array::Array;
4+
use defines::AfError;
5+
use defines::ColorMap;
6+
use self::libc::{c_int, c_uint, c_double};
7+
8+
type MutWndHandle = *mut self::libc::c_ulonglong;
9+
type WndHandle = self::libc::c_ulonglong;
10+
type AfArray = self::libc::c_longlong;
11+
type CellPtr = *const self::libc::c_void;
12+
13+
#[allow(dead_code)]
14+
extern {
15+
fn af_create_window(out: MutWndHandle, w: c_int, h: c_int, title: *const u8) -> c_int;
16+
fn af_set_position(wnd: WndHandle, x: c_uint, y: c_uint) -> c_int;
17+
fn af_set_title(wnd: WndHandle, title: *const u8) -> c_int;
18+
fn af_draw_image(wnd: WndHandle, arr: AfArray, props: CellPtr) -> c_int;
19+
fn af_draw_plot(wnd: WndHandle, x: AfArray, y: AfArray, props: CellPtr) -> c_int;
20+
fn af_grid(wnd: WndHandle, rows: c_int, cols: c_int) -> c_int;
21+
fn af_show(wnd: WndHandle) -> c_int;
22+
fn af_is_window_closed(out: *mut c_int, wnd: WndHandle) -> c_int;
23+
fn af_destroy_window(wnd: WndHandle) -> c_int;
24+
25+
fn af_draw_hist(wnd: WndHandle, x: AfArray,
26+
minval: c_double, maxval: c_double, props: CellPtr) -> c_int;
27+
}
28+
29+
#[repr(C)]
30+
pub struct Cell {
31+
pub row: i32,
32+
pub col: i32,
33+
pub title: String,
34+
pub cmap: ColorMap,
35+
}
36+
37+
#[derive(Clone)]
38+
pub struct Window {
39+
handle: u64,
40+
row: i32,
41+
col: i32,
42+
cmap: ColorMap,
43+
}
44+
45+
impl From<u64> for Window {
46+
fn from(t: u64) -> Window {
47+
Window {handle: t, row: -1, col: -1, cmap: ColorMap::DEFAULT}
48+
}
49+
}
50+
51+
impl Drop for Window {
52+
fn drop(&mut self) {
53+
unsafe {
54+
let err_val = af_destroy_window(self.handle);
55+
match err_val {
56+
0 => (),
57+
_ => panic!("Window object destruction failed with error code: {}", err_val),
58+
}
59+
}
60+
}
61+
}
62+
63+
impl Window {
64+
#[allow(unused_mut)]
65+
pub fn new(width: i32, height: i32, title: String) -> Result<Window, AfError> {
66+
unsafe {
67+
let mut temp: u64 = 0;
68+
let err_val = af_create_window(&mut temp as MutWndHandle,
69+
width as c_int, height as c_int,
70+
title.as_bytes().as_ptr() as *const u8);
71+
match err_val {
72+
0 => Ok(Window::from(temp)),
73+
_ => Err(AfError::from(err_val)),
74+
}
75+
}
76+
}
77+
78+
pub fn set_position(&self, x: u32, y: u32) -> Result<(), AfError> {
79+
unsafe {
80+
let err_val = af_set_position(self.handle as WndHandle, x as c_uint, y as c_uint);
81+
match err_val {
82+
0 => Ok(()),
83+
_ => Err(AfError::from(err_val)),
84+
}
85+
}
86+
}
87+
88+
pub fn set_title(&self, title: String) -> Result<(), AfError> {
89+
unsafe {
90+
let err_val = af_set_title(self.handle as WndHandle,
91+
title.as_bytes().as_ptr() as *const u8);
92+
match err_val {
93+
0 => Ok(()),
94+
_ => Err(AfError::from(err_val)),
95+
}
96+
}
97+
}
98+
99+
pub fn set_colormap(&mut self, cmap: ColorMap) {
100+
self.cmap = cmap;
101+
}
102+
103+
pub fn is_closed(&self) -> Result<bool, AfError> {
104+
unsafe {
105+
let mut temp: i32 = 1;
106+
let err_val = af_is_window_closed(&mut temp as *mut c_int, self.handle as WndHandle);
107+
match err_val {
108+
0 => Ok(temp > 0),
109+
_ => Err(AfError::from(err_val)),
110+
}
111+
}
112+
}
113+
114+
pub fn grid(&self, rows: i32, cols: i32) -> Result<(), AfError> {
115+
unsafe {
116+
let err_val = af_grid(self.handle as WndHandle, rows as c_int, cols as c_int);
117+
match err_val {
118+
0 => Ok(()),
119+
_ => Err(AfError::from(err_val)),
120+
}
121+
}
122+
}
123+
124+
pub fn show(&mut self) -> Result<(), AfError> {
125+
unsafe {
126+
let err_val = af_show(self.handle as WndHandle);
127+
if err_val != 0 {
128+
return Err(AfError::from(err_val));
129+
}
130+
self.row = -1;
131+
self.col = -1;
132+
Ok(())
133+
}
134+
}
135+
136+
pub fn set_view(&mut self, r: i32, c: i32) {
137+
self.row = r;
138+
self.col = c;
139+
}
140+
141+
pub fn draw_image(&self, input: &Array, title: Option<String>) {
142+
let tstr = match title {
143+
Some(s) => s,
144+
None => format!("Cell({},{}))", self.col, self.row)
145+
};
146+
let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap};
147+
unsafe {
148+
let err_val = af_draw_image(self.handle as WndHandle, input.get() as AfArray,
149+
cprops as *const Cell as CellPtr);
150+
match err_val {
151+
0 => (),
152+
_ => panic!("Rendering the image failed: {}", err_val),
153+
}
154+
}
155+
}
156+
157+
pub fn draw_plot(&self, x: &Array, y: &Array, title: Option<String>) {
158+
let tstr = match title {
159+
Some(s) => s,
160+
None => format!("Cell({},{}))", self.col, self.row)
161+
};
162+
let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap};
163+
unsafe {
164+
let err_val = af_draw_plot(self.handle as WndHandle,
165+
x.get() as AfArray,
166+
y.get() as AfArray,
167+
cprops as *const Cell as CellPtr);
168+
match err_val {
169+
0 => (),
170+
_ => panic!("Rendering the image failed: {}", err_val),
171+
}
172+
}
173+
}
174+
175+
pub fn draw_hist(&self, hst: &Array, minval: f64, maxval: f64, title: Option<String>) {
176+
let tstr = match title {
177+
Some(s) => s,
178+
None => format!("Cell({},{}))", self.col, self.row)
179+
};
180+
let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap};
181+
unsafe {
182+
let err_val = af_draw_hist(self.handle as WndHandle, hst.get() as AfArray,
183+
minval as c_double, maxval as c_double,
184+
cprops as *const Cell as CellPtr);
185+
match err_val {
186+
0 => (),
187+
_ => panic!("Rendering the image failed: {}", err_val),
188+
}
189+
}
190+
}
191+
}

src/image/mod.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,12 @@ pub fn gradient(input: &Array) -> Result<(Array, Array), AfError> {
8989
}
9090

9191
#[allow(unused_mut)]
92-
pub fn load_image(filename: &[u8], is_color: bool) -> Result<Array, AfError> {
92+
pub fn load_image(filename: String, is_color: bool) -> Result<Array, AfError> {
9393
unsafe {
9494
let mut temp: i64 = 0;
9595
let err_val = af_load_image(&mut temp as MutAfArray,
96-
filename.as_ptr() as *const u8, is_color as c_int);
96+
filename.as_bytes().as_ptr() as *const u8,
97+
is_color as c_int);
9798
match err_val {
9899
0 => Ok(Array::from(temp)),
99100
_ => Err(AfError::from(err_val)),
@@ -102,9 +103,10 @@ pub fn load_image(filename: &[u8], is_color: bool) -> Result<Array, AfError> {
102103
}
103104

104105
#[allow(unused_mut)]
105-
pub fn save_image(filename: &[u8], input: &Array) -> Result<(), AfError> {
106+
pub fn save_image(filename: String, input: &Array) -> Result<(), AfError> {
106107
unsafe {
107-
let err_val = af_save_image(filename.as_ptr() as *const u8, input.get() as AfArray);
108+
let err_val = af_save_image(filename.as_bytes().as_ptr() as *const u8,
109+
input.get() as AfArray);
108110
match err_val {
109111
0 => Ok(()),
110112
_ => Err(AfError::from(err_val)),
@@ -266,7 +268,7 @@ pub fn mean_shift(input: &Array, spatial_sigma: f32, chromatic_sigma: f32,
266268
macro_rules! filt_func_def {
267269
($fn_name: ident, $ffi_name: ident) => (
268270
#[allow(unused_mut)]
269-
pub fn $fn_name(input: &Array, wlen: i64, wwid: i64,
271+
pub fn $fn_name(input: &Array, wlen: u64, wwid: u64,
270272
etype: BorderType) -> Result<Array, AfError> {
271273
unsafe {
272274
let mut temp: i64 = 0;

src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,17 @@ mod data;
3232
pub use device::{get_version, info, set_device};
3333
mod device;
3434

35-
pub use defines::{Aftype, AfError};
35+
pub use defines::{Aftype, AfError, ColorMap};
3636
pub use defines::{InterpType, BorderType, MatchType, NormType};
3737
pub use defines::{Connectivity, ConvMode, ConvDomain, ColorSpace, MatProp};
3838
mod defines;
3939

4040
pub use dim4::Dim4;
4141
mod dim4;
4242

43+
pub use graphics::Window;
44+
mod graphics;
45+
4346
pub use image::{gaussian_kernel, load_image, save_image};
4447
pub use image::{resize, transform, rotate, translate, scale, skew};
4548
pub use image::{dilate, dilate3, erode, erode3, minfilt, maxfilt};

0 commit comments

Comments
 (0)