1use crate::blending::params::{BlendAlgorithmParams, Value};
4use crate::utils::{max, min};
5use image::Rgba;
6
7#[inline(always)]
8pub fn blend_alpha(
9 (bot_pixel, top_pixel): (&mut Rgba<u8>, &Rgba<u8>),
10 _params: &Option<BlendAlgorithmParams>,
11) {
12 let (rb, gb, bb, ab) = (bot_pixel[0], bot_pixel[1], bot_pixel[2], bot_pixel[3]);
13 let (rt, gt, bt, at) = (top_pixel[0], top_pixel[1], top_pixel[2], top_pixel[3]);
14
15 let abf = 1.0 * (ab as f32 / 255.0);
16 let atf = 1.0 * (at as f32 / 255.0);
17 let af = atf + abf * (1.0 - atf);
18
19 let mut r = if af == 0.0 {
20 0.0
21 } else {
22 (rb as f32 * abf + rt as f32 * atf * (1.0 - abf)) / af
23 };
24 let mut g = if af == 0.0 {
25 0.0
26 } else {
27 (gb as f32 * abf + gt as f32 * atf * (1.0 - abf)) / af
28 };
29 let mut b = if af == 0.0 {
30 0.0
31 } else {
32 (bb as f32 * abf + bt as f32 * atf * (1.0 - abf)) / af
33 };
34 let a = max(0.0, min(255.0, (abf + atf * (1.0 - abf)) * 255.0));
35
36 r = max(0.0, min(255.0, r));
37 g = max(0.0, min(255.0, g));
38 b = max(0.0, min(255.0, b));
39
40 bot_pixel[0] = r as u8;
41 bot_pixel[1] = g as u8;
42 bot_pixel[2] = b as u8;
43 bot_pixel[3] = a as u8;
44}
45
46#[inline(always)]
47pub fn blend_multiplicative(
48 (bot_pixel, top_pixel): (&mut Rgba<u8>, &Rgba<u8>),
49 _params: &Option<BlendAlgorithmParams>,
50) {
51 let (rb, gb, bb, ab) = (bot_pixel[0], bot_pixel[1], bot_pixel[2], bot_pixel[3]);
52 let (rt, gt, bt, at) = (top_pixel[0], top_pixel[1], top_pixel[2], top_pixel[3]);
53
54 let atf = 1.0 * (at as f32 / 255.0);
55
56 let mut r = rb as f32 * (1.0 - atf) + rt as f32 * atf;
57 let mut g = gb as f32 * (1.0 - atf) + gt as f32 * atf;
58 let mut b = bb as f32 * (1.0 - atf) + bt as f32 * atf;
59 let a = max(0, min(255, at as u16 + ab as u16));
60
61 r = max(0.0, min(255.0, r));
62 g = max(0.0, min(255.0, g));
63 b = max(0.0, min(255.0, b));
64
65 bot_pixel[0] = r as u8;
66 bot_pixel[1] = g as u8;
67 bot_pixel[2] = b as u8;
68 bot_pixel[3] = a as u8;
69}
70
71#[inline(always)]
72pub fn blend_source_over(
73 (bot_pixel, top_pixel): (&mut Rgba<u8>, &Rgba<u8>),
74 _params: &Option<BlendAlgorithmParams>,
75) {
76 let (rb, gb, bb, ab) = (bot_pixel[0], bot_pixel[1], bot_pixel[2], bot_pixel[3]);
77 let (rt, gt, bt, at) = (top_pixel[0], top_pixel[1], top_pixel[2], top_pixel[3]);
78
79 let abf = 1.0 * (ab as f32 / 255.0);
80 let atf = 1.0 * (at as f32 / 255.0);
81 let af = abf + atf * (1.0 - abf);
82
83 let mut r = if af == 0.0 {
84 0.0
85 } else {
86 (rb as f32 * abf + rt as f32 * atf * (1.0 - abf)) / af
87 };
88 let mut g = if af == 0.0 {
89 0.0
90 } else {
91 (gb as f32 * abf + gt as f32 * atf * (1.0 - abf)) / af
92 };
93 let mut b = if af == 0.0 {
94 0.0
95 } else {
96 (bb as f32 * abf + bt as f32 * atf * (1.0 - abf)) / af
97 };
98 let a = max(0.0, min(255.0, af * 255.0));
99
100 r = max(0.0, min(255.0, r));
101 g = max(0.0, min(255.0, g));
102 b = max(0.0, min(255.0, b));
103
104 bot_pixel[0] = r as u8;
105 bot_pixel[1] = g as u8;
106 bot_pixel[2] = b as u8;
107 bot_pixel[3] = a as u8;
108}
109
110#[inline(always)]
111pub fn blend_destination_over(
112 (bot_pixel, top_pixel): (&mut Rgba<u8>, &Rgba<u8>),
113 _params: &Option<BlendAlgorithmParams>,
114) {
115 let (rb, gb, bb, ab) = (bot_pixel[0], bot_pixel[1], bot_pixel[2], bot_pixel[3]);
116 let (rt, gt, bt, at) = (top_pixel[0], top_pixel[1], top_pixel[2], top_pixel[3]);
117
118 let abf = 1.0 * (ab as f32 / 255.0);
119 let atf = 1.0 * (at as f32 / 255.0);
120 let af = atf + abf * (1.0 - atf);
121
122 let mut r = if af == 0.0 {
123 0.0
124 } else {
125 (rt as f32 * atf + rb as f32 * abf * (1.0 - atf)) / af
126 };
127 let mut g = if af == 0.0 {
128 0.0
129 } else {
130 (gt as f32 * atf + gb as f32 * abf * (1.0 - atf)) / af
131 };
132 let mut b = if af == 0.0 {
133 0.0
134 } else {
135 (bt as f32 * atf + bb as f32 * abf * (1.0 - atf)) / af
136 };
137 let a = max(0.0, min(255.0, af * 255.0));
138
139 r = max(0.0, min(255.0, r));
140 g = max(0.0, min(255.0, g));
141 b = max(0.0, min(255.0, b));
142
143 bot_pixel[0] = r as u8;
144 bot_pixel[1] = g as u8;
145 bot_pixel[2] = b as u8;
146 bot_pixel[3] = a as u8;
147}
148
149#[inline(always)]
150pub fn blend_mask_top(
151 (bot_pixel, top_pixel): (&mut Rgba<u8>, &Rgba<u8>),
152 params: &Option<BlendAlgorithmParams>,
153) {
154 let (rb, gb, bb, ab) = (bot_pixel[0], bot_pixel[1], bot_pixel[2], bot_pixel[3]);
155 let (rt, gt, bt, at) = (top_pixel[0], top_pixel[1], top_pixel[2], top_pixel[3]);
156
157 let factor = params
158 .as_ref()
159 .and_then(|params| params.get("factor"))
160 .and_then(|param| match param {
161 Value::Float(float) => Some(*float),
162 _ => None,
163 })
164 .unwrap_or(1.0) as f32;
165
166 let atf = factor * (at as f32 / 255.0);
167 let abf = 1.0 - atf;
168
169 let mut r = rb as f32 * abf + rt as f32 * atf;
170 let mut g = gb as f32 * abf + gt as f32 * atf;
171 let mut b = bb as f32 * abf + bt as f32 * atf;
172 let mut a = ab as f32 * abf + at as f32 * atf;
173
174 r = max(0.0, min(255.0, r));
175 g = max(0.0, min(255.0, g));
176 b = max(0.0, min(255.0, b));
177 a = max(0.0, min(255.0, a));
178
179 bot_pixel[0] = r as u8;
180 bot_pixel[1] = g as u8;
181 bot_pixel[2] = b as u8;
182 bot_pixel[3] = a as u8;
183}
184
185#[inline(always)]
186pub fn blend_first_top(
187 (bot_pixel, top_pixel): (&mut Rgba<u8>, &Rgba<u8>),
188 _params: &Option<BlendAlgorithmParams>,
189) {
190 let (rb, gb, bb, ab) = (bot_pixel[0], bot_pixel[1], bot_pixel[2], bot_pixel[3]);
191 let (rt, gt, bt, at) = (top_pixel[0], top_pixel[1], top_pixel[2], top_pixel[3]);
192
193 let mut r = if at == 0 { rb } else { rt };
194 let mut g = if at == 0 { gb } else { gt };
195 let mut b = if at == 0 { bb } else { bt };
196 let mut a = if at == 0 { ab } else { at };
197
198 r = max(0, min(255, r));
199 g = max(0, min(255, g));
200 b = max(0, min(255, b));
201 a = max(0, min(255, a));
202
203 bot_pixel[0] = r;
204 bot_pixel[1] = g;
205 bot_pixel[2] = b;
206 bot_pixel[3] = a;
207}
208
209#[inline(always)]
210pub fn blend_first_bottom(
211 (bot_pixel, top_pixel): (&mut Rgba<u8>, &Rgba<u8>),
212 _params: &Option<BlendAlgorithmParams>,
213) {
214 let (rb, gb, bb, ab) = (bot_pixel[0], bot_pixel[1], bot_pixel[2], bot_pixel[3]);
215 let (rt, gt, bt, at) = (top_pixel[0], top_pixel[1], top_pixel[2], top_pixel[3]);
216
217 let mut r = if ab == 0 { rt } else { rb };
218 let mut g = if ab == 0 { gt } else { gb };
219 let mut b = if ab == 0 { bt } else { bb };
220 let mut a = if ab == 0 { at } else { ab };
221
222 r = max(0, min(255, r));
223 g = max(0, min(255, g));
224 b = max(0, min(255, b));
225 a = max(0, min(255, a));
226
227 bot_pixel[0] = r;
228 bot_pixel[1] = g;
229 bot_pixel[2] = b;
230 bot_pixel[3] = a;
231}
232
233#[inline(always)]
234pub fn blend_disjoint_over(
235 (bot_pixel, top_pixel): (&mut Rgba<u8>, &Rgba<u8>),
236 _params: &Option<BlendAlgorithmParams>,
237) {
238 let (rb, gb, bb, ab) = (bot_pixel[0], bot_pixel[1], bot_pixel[2], bot_pixel[3]);
239 let (rt, gt, bt, at) = (top_pixel[0], top_pixel[1], top_pixel[2], top_pixel[3]);
240
241 let abf = 1.0 * (ab as f32 / 255.0);
242 let atf = 1.0 * (at as f32 / 255.0);
243
244 let mut r = if atf + abf < 1.0 {
245 rt as f32 + rb as f32 * (1.0 - atf) / abf
246 } else {
247 rt as f32 + rb as f32
248 };
249 let mut g = if atf + abf < 1.0 {
250 gt as f32 + gb as f32 * (1.0 - atf) / abf
251 } else {
252 gt as f32 + gb as f32
253 };
254 let mut b = if atf + abf < 1.0 {
255 bt as f32 + bb as f32 * (1.0 - atf) / abf
256 } else {
257 bt as f32 + bb as f32
258 };
259 let a = max(0, min(255, at as u16 + ab as u16));
260
261 r = max(0.0, min(255.0, r));
262 g = max(0.0, min(255.0, g));
263 b = max(0.0, min(255.0, b));
264
265 bot_pixel[0] = r as u8;
266 bot_pixel[1] = g as u8;
267 bot_pixel[2] = b as u8;
268 bot_pixel[3] = a as u8;
269}
270
271#[inline(always)]
272pub fn blend_disjoint_under(
273 (bot_pixel, top_pixel): (&mut Rgba<u8>, &Rgba<u8>),
274 _params: &Option<BlendAlgorithmParams>,
275) {
276 let (rb, gb, bb, ab) = (bot_pixel[0], bot_pixel[1], bot_pixel[2], bot_pixel[3]);
277 let (rt, gt, bt, at) = (top_pixel[0], top_pixel[1], top_pixel[2], top_pixel[3]);
278
279 let abf = 1.0 * (ab as f32 / 255.0);
280 let atf = 1.0 * (at as f32 / 255.0);
281
282 let mut r = if atf * abf > 0.0 {
283 rt as f32 / atf * (1.0 - abf) + rb as f32
284 } else {
285 rt as f32 * (1.0 - abf) + rb as f32
286 };
287 let mut g = if atf * abf > 0.0 {
288 gt as f32 / atf * (1.0 - abf) + gb as f32
289 } else {
290 gt as f32 * (1.0 - abf) + gb as f32
291 };
292 let mut b = if atf * abf > 0.0 {
293 bt as f32 / atf * (1.0 - abf) + bb as f32
294 } else {
295 bt as f32 * (1.0 - abf) + bb as f32
296 };
297 let a = max(0, min(255, at as u16 + ab as u16));
298
299 r = max(0.0, min(255.0, r));
300 g = max(0.0, min(255.0, g));
301 b = max(0.0, min(255.0, b));
302
303 bot_pixel[0] = r as u8;
304 bot_pixel[1] = g as u8;
305 bot_pixel[2] = b as u8;
306 bot_pixel[3] = a as u8;
307}
308
309#[inline(always)]
310pub fn blend_disjoint_debug(
311 (bot_pixel, top_pixel): (&mut Rgba<u8>, &Rgba<u8>),
312 _params: &Option<BlendAlgorithmParams>,
313) {
314 let ab = bot_pixel[3];
315 let at = top_pixel[3];
316
317 let abf = 1.0 * (ab as f32 / 255.0);
318 let atf = 1.0 * (at as f32 / 255.0);
319
320 let mut r = if atf + abf < 1.0 { 0 } else { 255 };
321 let mut g = if atf + abf < 1.0 { 255 } else { 0 };
322 let mut b = 0;
323 let a = max(0, min(255, at as u16 + ab as u16));
324
325 r = max(0, min(255, r));
326 g = max(0, min(255, g));
327 b = max(0, min(255, b));
328
329 bot_pixel[0] = r;
330 bot_pixel[1] = g;
331 bot_pixel[2] = b;
332 bot_pixel[3] = a as u8;
333}