一般采用以下脚本。
rust
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Pixel {
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
}
impl Pixel {
pub fn blend(p1: Pixel, p2: Pixel) -> Pixel {
let a1 = p1.a as u32;
let a2 = p2.a as u32;
let a3 = a2 + (a1 * (255 - a2) >> 8);
let x = a3 - a1;
let r = ((p1.r as u32 * a1 + p2.r as u32 * x) / a3) as u8;
let g = ((p1.g as u32 * a1 + p2.g as u32 * x) / a3) as u8;
let b = ((p1.b as u32 * a1 + p2.b as u32 * x) / a3) as u8;
let a = a3 as u8;
Pixel { r, g, b, a }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic() {
let p1 = Pixel { r: 255, g: 0, b: 0, a: 128 };
let p2 = Pixel { r: 0, g: 255, b: 0, a: 255 };
let blended = Pixel::blend(p1, p2);
println!("{:?}", blended);
}
}
若透明像素较多,考虑以下脚本。
rust
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Pixel {
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
}
impl Pixel {
pub fn blend(p1: Pixel, p2: Pixel) -> Pixel {
let a1 = p1.a as u32;
let a2 = p2.a as u32;
if a1 == 0 { return p2; }
if a2 == 0 { return p1; }
let a3 = a2 + (a1 * (255 - a2) >> 8);
let x = a3 - a1;
let r = ((p1.r as u32 * a1 + p2.r as u32 * x) / a3) as u8;
let g = ((p1.g as u32 * a1 + p2.g as u32 * x) / a3) as u8;
let b = ((p1.b as u32 * a1 + p2.b as u32 * x) / a3) as u8;
let a = a3 as u8;
Pixel { r, g, b, a }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic() {
let p1 = Pixel { r: 255, g: 0, b: 0, a: 128 };
let p2 = Pixel { r: 0, g: 255, b: 0, a: 255 };
let blended = Pixel::blend(p1, p2);
println!("{:?}", blended);
}
}