1 | // This Source Code Form is subject to the terms of the Mozilla Public |
2 | // License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. |
4 | |
5 | use super::{ImageRef, ImageRefMut}; |
6 | use usvg::filter::{ColorChannel, DisplacementMap}; |
7 | |
8 | /// Applies a displacement map. |
9 | /// |
10 | /// - `map` pixels should have a **unpremultiplied alpha**. |
11 | /// - `src` pixels can have any alpha method. |
12 | /// |
13 | /// `sx` and `sy` indicate canvas scale. |
14 | /// |
15 | /// # Panics |
16 | /// |
17 | /// When `src`, `map` and `dest` have different sizes. |
18 | pub fn apply( |
19 | fe: &DisplacementMap, |
20 | sx: f32, |
21 | sy: f32, |
22 | src: ImageRef, |
23 | map: ImageRef, |
24 | dest: ImageRefMut, |
25 | ) { |
26 | assert!(src.width == map.width && src.width == dest.width); |
27 | assert!(src.height == map.height && src.height == dest.height); |
28 | |
29 | let w = src.width as i32; |
30 | let h = src.height as i32; |
31 | |
32 | let mut x: u32 = 0; |
33 | let mut y: u32 = 0; |
34 | for pixel in map.data.iter() { |
35 | let calc_offset = |channel| { |
36 | let c = match channel { |
37 | ColorChannel::B => pixel.b, |
38 | ColorChannel::G => pixel.g, |
39 | ColorChannel::R => pixel.r, |
40 | ColorChannel::A => pixel.a, |
41 | }; |
42 | |
43 | c as f32 / 255.0 - 0.5 |
44 | }; |
45 | |
46 | let dx = calc_offset(fe.x_channel_selector()); |
47 | let dy = calc_offset(fe.y_channel_selector()); |
48 | let ox = (x as f32 + dx * sx * fe.scale()).round() as i32; |
49 | let oy = (y as f32 + dy * sy * fe.scale()).round() as i32; |
50 | |
51 | // TODO: we should use some kind of anti-aliasing when offset is on a pixel border |
52 | |
53 | if x < w as u32 && y < h as u32 && ox >= 0 && ox < w && oy >= 0 && oy < h { |
54 | let idx = (oy * w + ox) as usize; |
55 | let idx1 = (y * w as u32 + x) as usize; |
56 | dest.data[idx1] = src.data[idx]; |
57 | } |
58 | |
59 | x += 1; |
60 | if x == src.width { |
61 | x = 0; |
62 | y += 1; |
63 | } |
64 | } |
65 | } |
66 | |