基于rust的RGBA颜色混合
一般采用以下脚本。
#[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);}
}
若透明像素较多,考虑以下脚本。
#[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);}
}