pconvert_rust/blending/
algorithms.rs

1//! Low-level implementation of the blending algorithms.
2
3use 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}