Created
August 1, 2021 21:55
-
-
Save thomcc/60169e3d398015cf5091c8c0d94705bf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub type Argb8888 = u32; | |
/// Average of 2 pixels, rounding up on tie. | |
/// | |
/// It's fine if they're actually BGRA8888 or any other format, | |
/// this treats every channel the same. | |
pub fn pixel_average(c0: Argb8888, c1: Argb8888) -> Argb8888 { | |
(c0 | c1).wrapping_sub(((c0 ^ c1) >> 1) & 0x7f7f7f7f) | |
// version that rounds down: | |
// (c0 & c1).wrapping_add(((c0 ^ c1) >> 1) & 0x7f7f7f7f) | |
} | |
// pub just for easier asm viewing. | |
pub fn naive_pixel_average(a: Argb8888, b: Argb8888) -> Argb8888 { | |
let avg = |a: u8, b: u8| -> u8 { | |
// + 1 is to round up. | |
let v = (a as u32 + b as u32 + 1) / 2; | |
debug_assert!(v < 256, "{:?}", (a, b, v)); | |
v as u8 | |
}; | |
let abs = a.to_ne_bytes(); | |
let bbs = b.to_ne_bytes(); | |
u32::from_ne_bytes([ | |
avg(abs[0], bbs[0]), | |
avg(abs[1], bbs[1]), | |
avg(abs[2], bbs[2]), | |
avg(abs[3], bbs[3]), | |
]) | |
} | |
#[test] | |
fn check_pixavg() { | |
for ch0 in 0..=255 { | |
for ch1 in 0..=255 { | |
// more fun color bithacks: this is equivalent to | |
// `ch0 as u32 * 0x1010101` 😉 | |
let a = u32::from_ne_bytes([ch0, ch0, ch0, ch0]); | |
let b = u32::from_ne_bytes([ch1, ch1, ch1, ch1]); | |
check(a, b); | |
} | |
} | |
// smoke check to make sure nothing weird can happen, | |
// like overflow that crosses channels or something. | |
use rand::prelude::*; | |
let mut rng = thread_rng(); | |
for _ in 0..100000 { | |
check(rng.gen(), rng.gen()); | |
} | |
#[track_caller] | |
fn check(a: u32, b: u32) { | |
let avg0 = pixel_average(a, b); | |
let avg1 = naive_pixel_average(a, b); | |
assert_eq!(avg0, avg1, "{:#010x}, {:#010x} => {:#010x}, {:#010x}", a, b, avg0, avg1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment