sdl2/gfx/
imagefilter.rs

1//! MMX image filters
2
3use c_vec::CVec;
4use get_error;
5use libc::{self, c_int, c_uint, c_void, size_t};
6use std::mem;
7use sys::gfx::imagefilter;
8
9/// MMX detection routine (with override flag).
10pub 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.
15pub fn mmx_off() {
16    unsafe { imagefilter::SDL_imageFilterMMXoff() }
17}
18
19/// Enable MMX check for filter functions and use MMX code if available.
20pub fn mmx_on() {
21    unsafe { imagefilter::SDL_imageFilterMMXon() }
22}
23
24#[inline]
25fn 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| libc::free(p as *mut c_void))
29    }
30}
31
32/// Filter using Add: D = saturation255(S1 + S2).
33pub fn add(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
34    assert_eq!(src1.len(), src2.len());
35    let size = src1.len();
36    let dest = cvec_with_size(size);
37    let ret = unsafe {
38        imagefilter::SDL_imageFilterAdd(
39            mem::transmute(src1.get(0)),
40            mem::transmute(src2.get(0)),
41            mem::transmute(dest.get(0)),
42            size as c_uint,
43        )
44    };
45    if ret == 0 {
46        Ok(dest)
47    } else {
48        Err(get_error())
49    }
50}
51
52/// Filter using Mean: D = S1/2 + S2/2.
53pub fn mean(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
54    assert_eq!(src1.len(), src2.len());
55    let size = src1.len();
56    let dest = cvec_with_size(size);
57    let ret = unsafe {
58        imagefilter::SDL_imageFilterMean(
59            mem::transmute(src1.get(0)),
60            mem::transmute(src2.get(0)),
61            mem::transmute(dest.get(0)),
62            size as c_uint,
63        )
64    };
65    if ret == 0 {
66        Ok(dest)
67    } else {
68        Err(get_error())
69    }
70}
71
72/// Filter using Sub: D = saturation0(S1 - S2).
73pub fn sub(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
74    assert_eq!(src1.len(), src2.len());
75    let size = src1.len();
76    let dest = cvec_with_size(size);
77    let ret = unsafe {
78        imagefilter::SDL_imageFilterSub(
79            mem::transmute(src1.get(0)),
80            mem::transmute(src2.get(0)),
81            mem::transmute(dest.get(0)),
82            size as c_uint,
83        )
84    };
85    if ret == 0 {
86        Ok(dest)
87    } else {
88        Err(get_error())
89    }
90}
91
92/// Filter using `AbsDiff`: D = | S1 - S2 |.
93pub fn abs_diff(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
94    assert_eq!(src1.len(), src2.len());
95    let size = src1.len();
96    let dest = cvec_with_size(size);
97    let ret = unsafe {
98        imagefilter::SDL_imageFilterAbsDiff(
99            mem::transmute(src1.get(0)),
100            mem::transmute(src2.get(0)),
101            mem::transmute(dest.get(0)),
102            size as c_uint,
103        )
104    };
105    if ret == 0 {
106        Ok(dest)
107    } else {
108        Err(get_error())
109    }
110}
111
112/// Filter using Mult: D = saturation255(S1 * S2).
113pub fn mult(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 {
118        imagefilter::SDL_imageFilterMult(
119            mem::transmute(src1.get(0)),
120            mem::transmute(src2.get(0)),
121            mem::transmute(dest.get(0)),
122            size as c_uint,
123        )
124    };
125    if ret == 0 {
126        Ok(dest)
127    } else {
128        Err(get_error())
129    }
130}
131
132/// Filter using `MultNor`: D = S1 * S2.
133pub fn mult_nor(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
134    assert_eq!(src1.len(), src2.len());
135    let size = src1.len();
136    let dest = cvec_with_size(size);
137    let ret = unsafe {
138        imagefilter::SDL_imageFilterMultNor(
139            mem::transmute(src1.get(0)),
140            mem::transmute(src2.get(0)),
141            mem::transmute(dest.get(0)),
142            size as c_uint,
143        )
144    };
145    if ret == 0 {
146        Ok(dest)
147    } else {
148        Err(get_error())
149    }
150}
151
152/// Filter using `MultDivby2`: D = saturation255(S1/2 * S2).
153pub fn mult_div_by2(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
154    assert_eq!(src1.len(), src2.len());
155    let size = src1.len();
156    let dest = cvec_with_size(size);
157    let ret = unsafe {
158        imagefilter::SDL_imageFilterMultDivby2(
159            mem::transmute(src1.get(0)),
160            mem::transmute(src2.get(0)),
161            mem::transmute(dest.get(0)),
162            size as c_uint,
163        )
164    };
165    if ret == 0 {
166        Ok(dest)
167    } else {
168        Err(get_error())
169    }
170}
171
172/// Filter using `MultDivby4`: D = saturation255(S1/2 * S2/2).
173pub fn mult_div_by4(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
174    assert_eq!(src1.len(), src2.len());
175    let size = src1.len();
176    let dest = cvec_with_size(size);
177    let ret = unsafe {
178        imagefilter::SDL_imageFilterMultDivby4(
179            mem::transmute(src1.get(0)),
180            mem::transmute(src2.get(0)),
181            mem::transmute(dest.get(0)),
182            size as c_uint,
183        )
184    };
185    if ret == 0 {
186        Ok(dest)
187    } else {
188        Err(get_error())
189    }
190}
191
192/// Filter using `BitAnd`: D = S1 & S2.
193pub fn bit_and(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
194    assert_eq!(src1.len(), src2.len());
195    let size = src1.len();
196    let dest = cvec_with_size(size);
197    let ret = unsafe {
198        imagefilter::SDL_imageFilterBitAnd(
199            mem::transmute(src1.get(0)),
200            mem::transmute(src2.get(0)),
201            mem::transmute(dest.get(0)),
202            size as c_uint,
203        )
204    };
205    if ret == 0 {
206        Ok(dest)
207    } else {
208        Err(get_error())
209    }
210}
211
212/// Filter using `BitOr`: D = S1 | S2.
213pub fn bit_or(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
214    assert_eq!(src1.len(), src2.len());
215    let size = src1.len();
216    let dest = cvec_with_size(size);
217    let ret = unsafe {
218        imagefilter::SDL_imageFilterBitOr(
219            mem::transmute(src1.get(0)),
220            mem::transmute(src2.get(0)),
221            mem::transmute(dest.get(0)),
222            size as c_uint,
223        )
224    };
225    if ret == 0 {
226        Ok(dest)
227    } else {
228        Err(get_error())
229    }
230}
231
232/// Filter using Div: D = S1 / S2.
233pub fn div(src1: CVec<u8>, src2: CVec<u8>) -> Result<CVec<u8>, String> {
234    assert_eq!(src1.len(), src2.len());
235    let size = src1.len();
236    let dest = cvec_with_size(size);
237    let ret = unsafe {
238        imagefilter::SDL_imageFilterDiv(
239            mem::transmute(src1.get(0)),
240            mem::transmute(src2.get(0)),
241            mem::transmute(dest.get(0)),
242            size as c_uint,
243        )
244    };
245    if ret == 0 {
246        Ok(dest)
247    } else {
248        Err(get_error())
249    }
250}
251
252/// Filter using `BitNegation`: D = !S.
253pub fn bit_negation(src1: CVec<u8>) -> Result<CVec<u8>, String> {
254    let size = src1.len();
255    let dest = cvec_with_size(size);
256    let ret = unsafe {
257        imagefilter::SDL_imageFilterBitNegation(
258            mem::transmute(src1.get(0)),
259            mem::transmute(dest.get(0)),
260            size as c_uint,
261        )
262    };
263    if ret == 0 {
264        Ok(dest)
265    } else {
266        Err(get_error())
267    }
268}
269
270/// Filter using `AddByte`: D = saturation255(S + C).
271pub fn add_byte(src1: CVec<u8>, c: u8) -> Result<CVec<u8>, String> {
272    let size = src1.len();
273    let dest = cvec_with_size(size);
274    let ret = unsafe {
275        imagefilter::SDL_imageFilterAddByte(
276            mem::transmute(src1.get(0)),
277            mem::transmute(dest.get(0)),
278            size as c_uint,
279            c,
280        )
281    };
282    if ret == 0 {
283        Ok(dest)
284    } else {
285        Err(get_error())
286    }
287}
288
289/// Filter using `AddUint`: D = saturation255((S[i] + Cs[i % 4]), Cs=Swap32((uint)C).
290pub fn add_uint(src1: CVec<u8>, c: u32) -> Result<CVec<u8>, String> {
291    let size = src1.len();
292    let dest = cvec_with_size(size);
293    let ret = unsafe {
294        imagefilter::SDL_imageFilterAddUint(
295            mem::transmute(src1.get(0)),
296            mem::transmute(dest.get(0)),
297            size as c_uint,
298            c,
299        )
300    };
301    if ret == 0 {
302        Ok(dest)
303    } else {
304        Err(get_error())
305    }
306}
307
308/// Filter using `AddByteToHalf`: D = saturation255(S/2 + C).
309pub fn add_byte_to_half(src1: CVec<u8>, c: u8) -> Result<CVec<u8>, String> {
310    let size = src1.len();
311    let dest = cvec_with_size(size);
312    let ret = unsafe {
313        imagefilter::SDL_imageFilterAddByteToHalf(
314            mem::transmute(src1.get(0)),
315            mem::transmute(dest.get(0)),
316            size as c_uint,
317            c,
318        )
319    };
320    if ret == 0 {
321        Ok(dest)
322    } else {
323        Err(get_error())
324    }
325}
326
327/// Filter using `SubByte`: D = saturation0(S - C).
328pub fn sub_byte(src1: CVec<u8>, c: u8) -> Result<CVec<u8>, String> {
329    let size = src1.len();
330    let dest = cvec_with_size(size);
331    let ret = unsafe {
332        imagefilter::SDL_imageFilterSubByte(
333            mem::transmute(src1.get(0)),
334            mem::transmute(dest.get(0)),
335            size as c_uint,
336            c,
337        )
338    };
339    if ret == 0 {
340        Ok(dest)
341    } else {
342        Err(get_error())
343    }
344}
345
346/// Filter using `SubUint`: D = saturation0(S[i] - Cs[i % 4]), Cs=Swap32((uint)C).
347pub fn sub_uint(src1: CVec<u8>, c: u32) -> Result<CVec<u8>, String> {
348    let size = src1.len();
349    let dest = cvec_with_size(size);
350    let ret = unsafe {
351        imagefilter::SDL_imageFilterSubUint(
352            mem::transmute(src1.get(0)),
353            mem::transmute(dest.get(0)),
354            size as c_uint,
355            c,
356        )
357    };
358    if ret == 0 {
359        Ok(dest)
360    } else {
361        Err(get_error())
362    }
363}
364
365/// Filter using `ShiftRight`: D = saturation0(S >> N).
366pub fn shift_right(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String> {
367    let size = src1.len();
368    let dest = cvec_with_size(size);
369    let ret = unsafe {
370        imagefilter::SDL_imageFilterShiftRight(
371            mem::transmute(src1.get(0)),
372            mem::transmute(dest.get(0)),
373            size as c_uint,
374            n,
375        )
376    };
377    if ret == 0 {
378        Ok(dest)
379    } else {
380        Err(get_error())
381    }
382}
383
384/// Filter using `ShiftRightUint`: D = saturation0((uint)S[i] >> N).
385pub fn shift_right_uint(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String> {
386    let size = src1.len();
387    let dest = cvec_with_size(size);
388    let ret = unsafe {
389        imagefilter::SDL_imageFilterShiftRightUint(
390            mem::transmute(src1.get(0)),
391            mem::transmute(dest.get(0)),
392            size as c_uint,
393            n,
394        )
395    };
396    if ret == 0 {
397        Ok(dest)
398    } else {
399        Err(get_error())
400    }
401}
402
403/// Filter using `MultByByte`: D = saturation255(S * C).
404pub fn mult_by_byte(src1: CVec<u8>, c: u8) -> Result<CVec<u8>, String> {
405    let size = src1.len();
406    let dest = cvec_with_size(size);
407    let ret = unsafe {
408        imagefilter::SDL_imageFilterMultByByte(
409            mem::transmute(src1.get(0)),
410            mem::transmute(dest.get(0)),
411            size as c_uint,
412            c,
413        )
414    };
415    if ret == 0 {
416        Ok(dest)
417    } else {
418        Err(get_error())
419    }
420}
421
422/// Filter using `ShiftRightAndMultByByte`: D = saturation255((S >> N) * C).
423pub fn shift_right_and_mult_by_byte(src1: CVec<u8>, n: u8, c: u8) -> Result<CVec<u8>, String> {
424    let size = src1.len();
425    let dest = cvec_with_size(size);
426    let ret = unsafe {
427        imagefilter::SDL_imageFilterShiftRightAndMultByByte(
428            mem::transmute(src1.get(0)),
429            mem::transmute(dest.get(0)),
430            size as c_uint,
431            n,
432            c,
433        )
434    };
435    if ret == 0 {
436        Ok(dest)
437    } else {
438        Err(get_error())
439    }
440}
441
442/// Filter using `ShiftLeftByte`: D = (S << N).
443pub fn shift_left_byte(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String> {
444    let size = src1.len();
445    let dest = cvec_with_size(size);
446    let ret = unsafe {
447        imagefilter::SDL_imageFilterShiftLeftByte(
448            mem::transmute(src1.get(0)),
449            mem::transmute(dest.get(0)),
450            size as c_uint,
451            n,
452        )
453    };
454    if ret == 0 {
455        Ok(dest)
456    } else {
457        Err(get_error())
458    }
459}
460
461/// Filter using `ShiftLeftUint`: D = ((uint)S << N).
462pub fn shift_left_uint(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String> {
463    let size = src1.len();
464    let dest = cvec_with_size(size);
465    let ret = unsafe {
466        imagefilter::SDL_imageFilterShiftLeftUint(
467            mem::transmute(src1.get(0)),
468            mem::transmute(dest.get(0)),
469            size as c_uint,
470            n,
471        )
472    };
473    if ret == 0 {
474        Ok(dest)
475    } else {
476        Err(get_error())
477    }
478}
479
480/// Filter `ShiftLeft`: D = saturation255(S << N).
481pub fn shift_left(src1: CVec<u8>, n: u8) -> Result<CVec<u8>, String> {
482    let size = src1.len();
483    let dest = cvec_with_size(size);
484    let ret = unsafe {
485        imagefilter::SDL_imageFilterShiftLeft(
486            mem::transmute(src1.get(0)),
487            mem::transmute(dest.get(0)),
488            size as c_uint,
489            n,
490        )
491    };
492    if ret == 0 {
493        Ok(dest)
494    } else {
495        Err(get_error())
496    }
497}
498
499/// Filter using `BinarizeUsingThreshold`: D = (S >= T) ? 255:0.
500pub fn binarize_using_threshold(src1: CVec<u8>, t: u8) -> Result<CVec<u8>, String> {
501    let size = src1.len();
502    let dest = cvec_with_size(size);
503    let ret = unsafe {
504        imagefilter::SDL_imageFilterBinarizeUsingThreshold(
505            mem::transmute(src1.get(0)),
506            mem::transmute(dest.get(0)),
507            size as c_uint,
508            t,
509        )
510    };
511    if ret == 0 {
512        Ok(dest)
513    } else {
514        Err(get_error())
515    }
516}
517
518/// Filter using `ClipToRange`: D = (S >= Tmin) & (S <= Tmax) S:Tmin | Tmax.
519pub fn clip_to_range(src1: CVec<u8>, tmin: u8, tmax: u8) -> Result<CVec<u8>, String> {
520    let size = src1.len();
521    let dest = cvec_with_size(size);
522    let ret = unsafe {
523        imagefilter::SDL_imageFilterClipToRange(
524            mem::transmute(src1.get(0)),
525            mem::transmute(dest.get(0)),
526            size as c_uint,
527            tmin,
528            tmax,
529        )
530    };
531    if ret == 0 {
532        Ok(dest)
533    } else {
534        Err(get_error())
535    }
536}
537
538/// Filter using `NormalizeLinear`: D = saturation255((Nmax - Nmin)/(Cmax - Cmin)*(S - Cmin) + Nmin).
539pub fn normalize_linear(
540    src1: CVec<u8>,
541    cmin: i32,
542    cmax: i32,
543    nmin: i32,
544    nmax: i32,
545) -> Result<CVec<u8>, String> {
546    let size = src1.len();
547    let dest = cvec_with_size(size);
548    let ret = unsafe {
549        imagefilter::SDL_imageFilterNormalizeLinear(
550            mem::transmute(src1.get(0)),
551            mem::transmute(dest.get(0)),
552            size as c_uint,
553            cmin as c_int,
554            cmax as c_int,
555            nmin as c_int,
556            nmax as c_int,
557        )
558    };
559    if ret == 0 {
560        Ok(dest)
561    } else {
562        Err(get_error())
563    }
564}