captcha/filters/
wave.rs

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
use std::f64::consts;

use filters::Filter;
use images::Image;

pub enum Direction {
    HORIZONTAL,
    VERTICAL,
}

pub struct Wave {
    f: f64,
    amp: f64,
    d: Direction,
}

impl Wave {
    pub fn new(f: f64, amp: f64) -> Wave {
        Wave {
            f,
            amp,
            d: Direction::HORIZONTAL,
        }
    }

    pub fn horizontal(self) -> Wave {
        Wave {
            d: Direction::HORIZONTAL,
            ..self
        }
    }

    pub fn vertical(self) -> Wave {
        Wave {
            d: Direction::VERTICAL,
            ..self
        }
    }

    pub fn direction(self, d: Direction) -> Wave {
        Wave { d, ..self }
    }
}

// TODO randomize offset

impl Filter for Wave {
    fn apply(&self, i: &mut Image) {
        let o = i.clone();
        i.clear();
        match self.d {
            Direction::HORIZONTAL => {
                // height of image changes
                for x in 0..i.width() {
                    let f =
                        (x as f64 * 2.0 * consts::PI * self.f / i.width() as f64).sin() * self.amp;
                    for y in 0..i.height() {
                        let ny = y as i32 - f as i32;
                        if ny >= 0 && ny < i.height() as i32 {
                            i.put_pixel(x, ny as u32, o.get_pixel(x, y));
                        }
                    }
                }
            }
            Direction::VERTICAL => {
                for y in 0..i.height() {
                    let f =
                        (y as f64 * 2.0 * consts::PI * self.f / i.width() as f64).sin() * self.amp;
                    for x in 0..i.width() {
                        let nx = x as i32 - f as i32;
                        if nx >= 0 && nx < i.width() as i32 {
                            i.put_pixel(nx as u32, y, o.get_pixel(x, y));
                        }
                    }
                }
            }
        }
    }
}