aboutsummaryrefslogtreecommitdiffstats
path: root/components/pixels/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/pixels/lib.rs')
-rw-r--r--components/pixels/lib.rs64
1 files changed, 64 insertions, 0 deletions
diff --git a/components/pixels/lib.rs b/components/pixels/lib.rs
index 7cba060ec74..24386ff830a 100644
--- a/components/pixels/lib.rs
+++ b/components/pixels/lib.rs
@@ -84,6 +84,7 @@ pub fn rgba8_premultiply_inplace(pixels: &mut [u8]) -> bool {
is_opaque
}
+#[inline(always)]
pub fn multiply_u8_color(a: u8, b: u8) -> u8 {
(a as u32 * b as u32 / 255) as u8
}
@@ -254,6 +255,69 @@ pub fn unmultiply_inplace<const SWAP_RB: bool>(pixels: &mut [u8]) {
}
}
+#[repr(u8)]
+pub enum Multiply {
+ None = 0,
+ PreMultiply = 1,
+ UnMultiply = 2,
+}
+
+pub fn transform_inplace(pixels: &mut [u8], multiply: Multiply, swap_rb: bool, clear_alpha: bool) {
+ match (multiply, swap_rb, clear_alpha) {
+ (Multiply::None, true, true) => generic_transform_inplace::<0, true, true>(pixels),
+ (Multiply::None, true, false) => generic_transform_inplace::<0, true, false>(pixels),
+ (Multiply::None, false, true) => generic_transform_inplace::<0, false, true>(pixels),
+ (Multiply::None, false, false) => generic_transform_inplace::<0, false, false>(pixels),
+ (Multiply::PreMultiply, true, true) => generic_transform_inplace::<1, true, true>(pixels),
+ (Multiply::PreMultiply, true, false) => generic_transform_inplace::<1, true, false>(pixels),
+ (Multiply::PreMultiply, false, true) => generic_transform_inplace::<1, false, true>(pixels),
+ (Multiply::PreMultiply, false, false) => {
+ generic_transform_inplace::<1, false, false>(pixels)
+ },
+ (Multiply::UnMultiply, true, true) => generic_transform_inplace::<2, true, true>(pixels),
+ (Multiply::UnMultiply, true, false) => generic_transform_inplace::<2, true, false>(pixels),
+ (Multiply::UnMultiply, false, true) => generic_transform_inplace::<2, false, true>(pixels),
+ (Multiply::UnMultiply, false, false) => {
+ generic_transform_inplace::<2, false, false>(pixels)
+ },
+ }
+}
+
+pub fn generic_transform_inplace<
+ const MULTIPLY: u8, // 1 premultiply, 2 unmultiply
+ const SWAP_RB: bool,
+ const CLEAR_ALPHA: bool,
+>(
+ pixels: &mut [u8],
+) {
+ for rgba in pixels.chunks_mut(4) {
+ match MULTIPLY {
+ 1 => {
+ let a = rgba[3];
+ multiply_u8_color(rgba[0], a);
+ multiply_u8_color(rgba[1], a);
+ multiply_u8_color(rgba[2], a);
+ },
+ 2 => {
+ let a = rgba[3] as u32;
+
+ if a > 0 {
+ rgba[0] = (rgba[0] as u32 * 255 / a) as u8;
+ rgba[1] = (rgba[1] as u32 * 255 / a) as u8;
+ rgba[2] = (rgba[2] as u32 * 255 / a) as u8;
+ }
+ },
+ _ => {},
+ }
+ if SWAP_RB {
+ rgba.swap(0, 2);
+ }
+ if CLEAR_ALPHA {
+ rgba[3] = u8::MAX;
+ }
+ }
+}
+
fn is_gif(buffer: &[u8]) -> bool {
buffer.starts_with(b"GIF87a") || buffer.starts_with(b"GIF89a")
}