1 //! MMX image filters
2
3 use std::mem;
4 use libc::{self,size_t, c_void, c_uint, c_int};
5 use ::get_error;
6 use c_vec::CVec;
7 use sys::gfx::imagefilter;
8
9 /// MMX detection routine (with override flag).
mmx_detect() -> bool10 pub fn mmx_detect() -> bool {
11 unsafe { imagefilter::SDL_imageFilterMMXdetect() == 1 }
12 }
13
14 /// Disable MMX check for filter functions and and force to use non-MMX C based code.
mmx_off()15 pub fn mmx_off() {
16 unsafe { imagefilter::SDL_imageFilterMMXoff() }
17 }
18
19 /// Enable MMX check for filter functions and use MMX code if available.
mmx_on()20 pub fn mmx_on() {
21 unsafe { imagefilter::SDL_imageFilterMMXon() }
22 }
23
24 #[inline]
cvec_with_size(sz: usize) -> CVec<u8>25 fn cvec_with_size(sz: usize) -> CVec<u8> {
26 unsafe {
27 let p = libc::malloc(sz as size_t) as *mut u8;
28 CVec::new_with_dtor(p, sz, move |p| {
29 libc::free(p as *mut c_void)
30 })
31 }
32 }
33
34 /// Filter using Add: D = saturation255(S1 + S2).
add(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String>35 pub fn add(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
36 assert_eq!(src1.len(), src2.len());
37 let size = src1.len();
38 let dest = cvec_with_size(size);
39 let ret = unsafe { imagefilter::SDL_imageFilterAdd(mem::transmute(src1.get(0)),
40 mem::transmute(src2.get(0)),
41 mem::transmute(dest.get(0)),
42 size as c_uint) };
43 if ret == 0 { Ok(dest) }
44 else { Err(get_error()) }
45 }
46
47 /// Filter using Mean: D = S1/2 + S2/2.
mean(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String>48 pub fn mean(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
49 assert_eq!(src1.len(), src2.len());
50 let size = src1.len();
51 let dest = cvec_with_size(size);
52 let ret = unsafe { imagefilter::SDL_imageFilterMean(mem::transmute(src1.get(0)),
53 mem::transmute(src2.get(0)),
54 mem::transmute(dest.get(0)),
55 size as c_uint) };
56 if ret == 0 { Ok(dest) }
57 else { Err(get_error()) }
58 }
59
60 /// Filter using Sub: D = saturation0(S1 - S2).
sub(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String>61 pub fn sub(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
62 assert_eq!(src1.len(), src2.len());
63 let size = src1.len();
64 let dest = cvec_with_size(size);
65 let ret = unsafe { imagefilter::SDL_imageFilterSub(mem::transmute(src1.get(0)),
66 mem::transmute(src2.get(0)),
67 mem::transmute(dest.get(0)),
68 size as c_uint) };
69 if ret == 0 { Ok(dest) }
70 else { Err(get_error()) }
71 }
72
73 /// Filter using `AbsDiff`: D = | S1 - S2 |.
abs_diff(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String>74 pub fn abs_diff(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
75 assert_eq!(src1.len(), src2.len());
76 let size = src1.len();
77 let dest = cvec_with_size(size);
78 let ret = unsafe { imagefilter::SDL_imageFilterAbsDiff(mem::transmute(src1.get(0)),
79 mem::transmute(src2.get(0)),
80 mem::transmute(dest.get(0)),
81 size as c_uint) };
82 if ret == 0 { Ok(dest) }
83 else { Err(get_error()) }
84 }
85
86 /// Filter using Mult: D = saturation255(S1 * S2).
mult(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String>87 pub fn mult(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
88 assert_eq!(src1.len(), src2.len());
89 let size = src1.len();
90 let dest = cvec_with_size(size);
91 let ret = unsafe { imagefilter::SDL_imageFilterMult(mem::transmute(src1.get(0)),
92 mem::transmute(src2.get(0)),
93 mem::transmute(dest.get(0)),
94 size as c_uint) };
95 if ret == 0 { Ok(dest) }
96 else { Err(get_error()) }
97 }
98
99 /// Filter using `MultNor`: D = S1 * S2.
mult_nor(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String>100 pub fn mult_nor(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
101 assert_eq!(src1.len(), src2.len());
102 let size = src1.len();
103 let dest = cvec_with_size(size);
104 let ret = unsafe { imagefilter::SDL_imageFilterMultNor(mem::transmute(src1.get(0)),
105 mem::transmute(src2.get(0)),
106 mem::transmute(dest.get(0)),
107 size as c_uint) };
108 if ret == 0 { Ok(dest) }
109 else { Err(get_error()) }
110 }
111
112 /// Filter using `MultDivby2`: D = saturation255(S1/2 * S2).
mult_div_by2(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String>113 pub fn mult_div_by2(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
114 assert_eq!(src1.len(), src2.len());
115 let size = src1.len();
116 let dest = cvec_with_size(size);
117 let ret = unsafe { imagefilter::SDL_imageFilterMultDivby2(mem::transmute(src1.get(0)),
118 mem::transmute(src2.get(0)),
119 mem::transmute(dest.get(0)),
120 size as c_uint) };
121 if ret == 0 { Ok(dest) }
122 else { Err(get_error()) }
123 }
124
125 /// Filter using `MultDivby4`: D = saturation255(S1/2 * S2/2).
mult_div_by4(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String>126 pub fn mult_div_by4(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
127 assert_eq!(src1.len(), src2.len());
128 let size = src1.len();
129 let dest = cvec_with_size(size);
130 let ret = unsafe { imagefilter::SDL_imageFilterMultDivby4(mem::transmute(src1.get(0)),
131 mem::transmute(src2.get(0)),
132 mem::transmute(dest.get(0)),
133 size as c_uint) };
134 if ret == 0 { Ok(dest) }
135 else { Err(get_error()) }
136 }
137
138 /// Filter using `BitAnd`: D = S1 & S2.
bit_and(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String>139 pub fn bit_and(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
140 assert_eq!(src1.len(), src2.len());
141 let size = src1.len();
142 let dest = cvec_with_size(size);
143 let ret = unsafe { imagefilter::SDL_imageFilterBitAnd(mem::transmute(src1.get(0)),
144 mem::transmute(src2.get(0)),
145 mem::transmute(dest.get(0)),
146 size as c_uint) };
147 if ret == 0 { Ok(dest) }
148 else { Err(get_error()) }
149 }
150
151 /// Filter using `BitOr`: D = S1 | S2.
bit_or(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String>152 pub fn bit_or(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
153 assert_eq!(src1.len(), src2.len());
154 let size = src1.len();
155 let dest = cvec_with_size(size);
156 let ret = unsafe { imagefilter::SDL_imageFilterBitOr(mem::transmute(src1.get(0)),
157 mem::transmute(src2.get(0)),
158 mem::transmute(dest.get(0)),
159 size as c_uint) };
160 if ret == 0 { Ok(dest) }
161 else { Err(get_error()) }
162 }
163
164 /// Filter using Div: D = S1 / S2.
div(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String>165 pub fn div(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
166 assert_eq!(src1.len(), src2.len());
167 let size = src1.len();
168 let dest = cvec_with_size(size);
169 let ret = unsafe { imagefilter::SDL_imageFilterDiv(mem::transmute(src1.get(0)),
170 mem::transmute(src2.get(0)),
171 mem::transmute(dest.get(0)),
172 size as c_uint) };
173 if ret == 0 { Ok(dest) }
174 else { Err(get_error()) }
175 }
176
177 /// Filter using `BitNegation`: D = !S.
bit_negation(src1: CVec<u8>) -> Result<CVec<u8>, String>178 pub fn bit_negation(src1: CVec<u8>) -> Result<CVec<u8>, String> {
179 let size = src1.len();
180 let dest = cvec_with_size(size);
181 let ret = unsafe { imagefilter::SDL_imageFilterBitNegation(mem::transmute(src1.get(0)),
182 mem::transmute(dest.get(0)),
183 size as c_uint) };
184 if ret == 0 { Ok(dest) }
185 else { Err(get_error()) }
186 }
187
188 /// Filter using `AddByte`: D = saturation255(S + C).
add_byte(src1: CVec<u8>, c: u8) -> Result<CVec<u8>, String>189 pub fn add_byte(src1: CVec<u8>, c: u8) -> Result<CVec<u8>, String> {
190 let size = src1.len();
191 let dest = cvec_with_size(size);
192 let ret = unsafe { imagefilter::SDL_imageFilterAddByte(mem::transmute(src1.get(0)),
193 mem::transmute(dest.get(0)),
194 size as c_uint, c) };
195 if ret == 0 { Ok(dest) }
196 else { Err(get_error()) }
197 }
198
199 /// Filter using `AddUint`: D = saturation255((S[i] + Cs[i % 4]), Cs=Swap32((uint)C).
add_uint(src1: CVec<u8>, c: u32) -> Result<CVec<u8>, String>200 pub fn add_uint(src1: CVec<u8>, c: u32) -> Result<CVec<u8>, String> {
201 let size = src1.len();
202 let dest = cvec_with_size(size);
203 let ret = unsafe { imagefilter::SDL_imageFilterAddUint(mem::transmute(src1.get(0)),
204 mem::transmute(dest.get(0)),
205 size as c_uint, c) };
206 if ret == 0 { Ok(dest) }
207 else { Err(get_error()) }
208 }
209
210 /// Filter using `AddByteToHalf`: D = saturation255(S/2 + C).
add_byte_to_half(src1: CVec<u8>, c: u8) -> Result<CVec<u8>, String>211 pub fn add_byte_to_half(src1: CVec<u8>, c: u8) -> Result<CVec<u8>, String> {
212 let size = src1.len();
213 let dest = cvec_with_size(size);
214 let ret = unsafe { imagefilter::SDL_imageFilterAddByteToHalf(mem::transmute(src1.get(0)),
215 mem::transmute(dest.get(0)),
216 size as c_uint, c) };
217 if ret == 0 { Ok(dest) }
218 else { Err(get_error()) }
219 }
220
221 /// Filter using `SubByte`: D = saturation0(S - C).
sub_byte(src1: CVec<u8>, c: u8) -> Result<CVec<u8>, String>222 pub fn sub_byte(src1: CVec<u8>, c: u8) -> Result<CVec<u8>, String> {
223 let size = src1.len();
224 let dest = cvec_with_size(size);
225 let ret = unsafe { imagefilter::SDL_imageFilterSubByte(mem::transmute(src1.get(0)),
226 mem::transmute(dest.get(0)),
227 size as c_uint, c) };
228 if ret == 0 { Ok(dest) }
229 else { Err(get_error()) }
230 }
231
232 /// Filter using `SubUint`: D = saturation0(S[i] - Cs[i % 4]), Cs=Swap32((uint)C).
sub_uint(src1: CVec<u8>, c: u32) -> Result<CVec<u8>, String>233 pub fn sub_uint(src1: CVec<u8>, c: u32) -> Result<CVec<u8>, String> {
234 let size = src1.len();
235 let dest = cvec_with_size(size);
236 let ret = unsafe { imagefilter::SDL_imageFilterSubUint(mem::transmute(src1.get(0)),
237 mem::transmute(dest.get(0)),
238 size as c_uint, c) };
239 if ret == 0 { Ok(dest) }
240 else { Err(get_error()) }
241 }
242
243 /// Filter using `ShiftRight`: D = saturation0(S >> N).
shift_right(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String>244 pub fn shift_right(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String> {
245 let size = src1.len();
246 let dest = cvec_with_size(size);
247 let ret = unsafe { imagefilter::SDL_imageFilterShiftRight(mem::transmute(src1.get(0)),
248 mem::transmute(dest.get(0)),
249 size as c_uint, n) };
250 if ret == 0 { Ok(dest) }
251 else { Err(get_error()) }
252 }
253
254 /// Filter using `ShiftRightUint`: D = saturation0((uint)S[i] >> N).
shift_right_uint(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String>255 pub fn shift_right_uint(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String> {
256 let size = src1.len();
257 let dest = cvec_with_size(size);
258 let ret = unsafe { imagefilter::SDL_imageFilterShiftRightUint(mem::transmute(src1.get(0)),
259 mem::transmute(dest.get(0)),
260 size as c_uint, n) };
261 if ret == 0 { Ok(dest) }
262 else { Err(get_error()) }
263 }
264
265 /// Filter using `MultByByte`: D = saturation255(S * C).
mult_by_byte(src1: CVec<u8>, c: u8) -> Result<CVec<u8>, String>266 pub fn mult_by_byte(src1: CVec<u8>, c: u8) -> Result<CVec<u8>, String> {
267 let size = src1.len();
268 let dest = cvec_with_size(size);
269 let ret = unsafe { imagefilter::SDL_imageFilterMultByByte(mem::transmute(src1.get(0)),
270 mem::transmute(dest.get(0)),
271 size as c_uint, c) };
272 if ret == 0 { Ok(dest) }
273 else { Err(get_error()) }
274 }
275
276 /// Filter using `ShiftRightAndMultByByte`: D = saturation255((S >> N) * C).
shift_right_and_mult_by_byte(src1: CVec<u8>, n: u8, c: u8) -> Result<CVec<u8>, String>277 pub fn shift_right_and_mult_by_byte(src1: CVec<u8>, n: u8, c: u8) -> Result<CVec<u8>, String> {
278 let size = src1.len();
279 let dest = cvec_with_size(size);
280 let ret = unsafe { imagefilter::SDL_imageFilterShiftRightAndMultByByte(mem::transmute(src1.get(0)),
281 mem::transmute(dest.get(0)),
282 size as c_uint, n, c) };
283 if ret == 0 { Ok(dest) }
284 else { Err(get_error()) }
285 }
286
287 /// Filter using `ShiftLeftByte`: D = (S << N).
shift_left_byte(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String>288 pub fn shift_left_byte(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String> {
289 let size = src1.len();
290 let dest = cvec_with_size(size);
291 let ret = unsafe { imagefilter::SDL_imageFilterShiftLeftByte(mem::transmute(src1.get(0)),
292 mem::transmute(dest.get(0)),
293 size as c_uint, n) };
294 if ret == 0 { Ok(dest) }
295 else { Err(get_error()) }
296 }
297
298 /// Filter using `ShiftLeftUint`: D = ((uint)S << N).
shift_left_uint(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String>299 pub fn shift_left_uint(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String> {
300 let size = src1.len();
301 let dest = cvec_with_size(size);
302 let ret = unsafe { imagefilter::SDL_imageFilterShiftLeftUint(mem::transmute(src1.get(0)),
303 mem::transmute(dest.get(0)),
304 size as c_uint, n) };
305 if ret == 0 { Ok(dest) }
306 else { Err(get_error()) }
307 }
308
309 /// Filter `ShiftLeft`: D = saturation255(S << N).
shift_left(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String>310 pub fn shift_left(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String> {
311 let size = src1.len();
312 let dest = cvec_with_size(size);
313 let ret = unsafe { imagefilter::SDL_imageFilterShiftLeft(mem::transmute(src1.get(0)),
314 mem::transmute(dest.get(0)),
315 size as c_uint, n) };
316 if ret == 0 { Ok(dest) }
317 else { Err(get_error()) }
318 }
319
320 /// Filter using `BinarizeUsingThreshold`: D = (S >= T) ? 255:0.
binarize_using_threshold(src1: CVec<u8>, t: u8) -> Result<CVec<u8>, String>321 pub fn binarize_using_threshold(src1: CVec<u8>, t: u8) -> Result<CVec<u8>, String> {
322 let size = src1.len();
323 let dest = cvec_with_size(size);
324 let ret = unsafe { imagefilter::SDL_imageFilterBinarizeUsingThreshold(mem::transmute(src1.get(0)),
325 mem::transmute(dest.get(0)),
326 size as c_uint, t) };
327 if ret == 0 { Ok(dest) }
328 else { Err(get_error()) }
329 }
330
331 /// Filter using `ClipToRange`: D = (S >= Tmin) & (S <= Tmax) S:Tmin | Tmax.
clip_to_range(src1: CVec<u8>, tmin: u8, tmax: u8) -> Result<CVec<u8>, String>332 pub fn clip_to_range(src1: CVec<u8>, tmin: u8, tmax: u8) -> Result<CVec<u8>, String> {
333 let size = src1.len();
334 let dest = cvec_with_size(size);
335 let ret = unsafe { imagefilter::SDL_imageFilterClipToRange(mem::transmute(src1.get(0)),
336 mem::transmute(dest.get(0)),
337 size as c_uint, tmin, tmax) };
338 if ret == 0 { Ok(dest) }
339 else { Err(get_error()) }
340 }
341
342 /// Filter using `NormalizeLinear`: D = saturation255((Nmax - Nmin)/(Cmax - Cmin)*(S - Cmin) + Nmin).
normalize_linear(src1: CVec<u8>, cmin: i32, cmax: i32, nmin: i32, nmax: i32) -> Result<CVec<u8>, String>343 pub fn normalize_linear(src1: CVec<u8>, cmin: i32, cmax: i32, nmin: i32, nmax: i32) -> Result<CVec<u8>, String> {
344 let size = src1.len();
345 let dest = cvec_with_size(size);
346 let ret = unsafe { imagefilter::SDL_imageFilterNormalizeLinear(mem::transmute(src1.get(0)),
347 mem::transmute(dest.get(0)),
348 size as c_uint,
349 cmin as c_int, cmax as c_int,
350 nmin as c_int, nmax as c_int) };
351 if ret == 0 { Ok(dest) }
352 else { Err(get_error()) }
353 }
354