1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
extern crate fastwfc_sys;
extern crate image;
use fastwfc_sys::run_overlapping;
fn to_array_color_2d(input: image::RgbaImage) -> *mut fastwfc_sys::ArrayColor2D {
let (w, h) = input.dimensions();
let obj = Box::new(input.into_vec());
let arr: *const u8 = obj.as_ptr();
let ptr = Box::into_raw(obj);
unsafe {
let array2d = fastwfc_sys::new_array_color_2d();
fastwfc_sys::array_color_2d_set_height(array2d, h as i32);
fastwfc_sys::array_color_2d_set_width(array2d, w as i32);
fastwfc_sys::array_color_2d_set_data(
array2d,
arr as *mut fastwfc_sys::Color,
ptr as *mut ::std::os::raw::c_void,
);
return array2d;
}
}
fn from_array_color_2d(c: *mut fastwfc_sys::ArrayColor2D) -> Option<image::RgbaImage> {
unsafe {
if !(*c).init {
return None;
}
let w = fastwfc_sys::array_color_2d_get_width(c);
let h = fastwfc_sys::array_color_2d_get_height(c);
let data = fastwfc_sys::array_color_2d_get_data(c) as *mut u8;
let buf = ::std::slice::from_raw_parts(data, (w * h * 4) as usize).to_vec();
let img = image::RgbaImage::from_raw(w as u32, h as u32, buf);
img
}
}
fn destroy_arr_2d(c: *mut fastwfc_sys::ArrayColor2D) {
if ::std::ptr::null() != unsafe{(*c).ref_} {
let ptr = unsafe { fastwfc_sys::array_color_2d_get_ref(c) } as *mut Vec<u8>;
let obj: Box<Vec<u8>> = unsafe { Box::from_raw(ptr) };
::std::mem::drop(obj);
}
unsafe { fastwfc_sys::destroy_array_color_2d(c); }
}
#[derive(Clone, Copy)]
pub struct Overlapping {
pub periodic_input: bool,
pub periodic_output: bool,
pub out_height: u64,
pub out_width: u64,
pub symmetry: u8,
pub ground: bool,
pub pattern_size: u64,
}
impl Overlapping {
pub fn new( out_height: u64, out_width: u64, pattern_size: u64) -> Self {
Self {
periodic_input: false,
periodic_output: false,
out_height,
out_width,
symmetry: 8,
ground: false,
pattern_size,
}
}
pub fn symmetry(&mut self, value: u8) -> &mut Self {
self.symmetry = value;
self
}
pub fn ground(&mut self, value: bool) -> &mut Self {
self.ground = value;
self
}
pub fn periodic_input(&mut self, value: bool) -> &mut Self {
self.periodic_input = value;
self
}
pub fn periodic_output(&mut self, value: bool) -> &mut Self {
self.periodic_output = value;
self
}
fn as_ffi_opts(&self) -> fastwfc_sys::OverlappingWFCOptions {
fastwfc_sys::OverlappingWFCOptions {
periodic_input: self.periodic_input,
periodic_output: self.periodic_output,
out_height: self.out_height as u32,
out_width: self.out_width as u32,
symmetry: self.symmetry as u32,
ground: self.ground,
pattern_size: self.pattern_size as u32,
}
}
pub fn generate(&self, input: image::RgbaImage, tries: u32) -> Option<image::RgbaImage> {
let array2d = to_array_color_2d(input);
let ret = unsafe { run_overlapping(array2d, self.as_ffi_opts(), tries) };
destroy_arr_2d(array2d);
let result = from_array_color_2d(ret);
destroy_arr_2d(ret);
result
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_run_overlapping() {
let runner = Overlapping::new(100, 100, 2);
let input = image::open("../fastwfc-sys/fast-wfc/example/samples/Chess.png")
.unwrap()
.to_rgba();
let output = runner.generate(input, 100);
assert!(output.is_some());
}
}