Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/convert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#[inline]
pub(crate) fn premultiply(val: u8, alpha: u8) -> u8 {
// TODO: Do we need to optimize this using bit shifts or similar?
((val as u16 * alpha as u16) / 0xff) as u8
}

#[inline]
pub(crate) fn unpremultiply(val: u8, alpha: u8) -> u8 {
// TODO: Can we find a cleaner / more efficient way to implement this?
(val as u16 * u8::MAX as u16)
.checked_div(alpha as u16)
.unwrap_or(0)
.min(u8::MAX as u16) as u8
}
71 changes: 71 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
mod backend_dispatch;
mod backend_interface;
mod backends;
mod convert;
mod error;
mod format;
mod pixel;
Expand Down Expand Up @@ -623,6 +624,76 @@
.map(move |(x, pixel)| (x as u32, y as u32, pixel))
})
}

/// Convert the alpha mode of the buffer in place.
///
/// # Examples
///
/// Write to the buffer as-if it was [`AlphaMode::Ignored`], and convert afterwards if
/// necessary.
///
/// ```no_run
/// # let buffer: Buffer<'_> = unimplemented!();

Check failure on line 636 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Tests (nightly, aarch64-apple-ios-macabi, macos-latest)

expected item, found keyword `let`

Check failure on line 636 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Tests (nightly, aarch64-apple-darwin, macos-latest)

expected item, found keyword `let`

Check failure on line 636 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Tests (nightly, x86_64-pc-windows-msvc, windows-latest)

expected item, found keyword `let`

Check failure on line 636 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Tests (nightly, i686-pc-windows-msvc, windows-latest)

expected item, found keyword `let`

Check failure on line 636 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Tests (nightly, wasm32-unknown-unknown, ubuntu-latest, -Zbuild-std=panic_abort,std, -Ctarget-feat...

expected item, found keyword `let`

Check failure on line 636 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Tests (nightly, x86_64-unknown-linux-gnu, ubuntu-latest, kms)

expected item, found keyword `let`

Check failure on line 636 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Tests (nightly, wasm32-unknown-unknown, ubuntu-latest)

expected item, found keyword `let`
///
/// surface.supports_alpha_mode(AlphaMode::Ignored) {
/// surface.set_alpha_mode(AlphaMode::Ignored);
/// } else {
/// surface.set_alpha_mode(AlphaMode::Opaque);
/// }
///
/// for row in buffer.pixel_rows() {
/// for pixel in row {
/// // Write red pixels with an arbitrary alpha value.
/// pixel = Pixel::new_rgba(0xff, 0x00, 0x00, 0x7f);
/// }
/// }
///
/// buffer.make_pixels_opaque();
///
/// // Alpha value is ignored, either by compositor () or by us above.
/// buffer.present();
/// ```
#[inline]
pub fn make_pixels_opaque(&mut self) {
if self.alpha_mode == AlphaMode::Ignored {
// Alpha mode is ignored, no need to change the pixels
return;
}
for row in self.pixel_rows() {
for pixel in row {
// TODO: SIMD-optimize this somehow? Or maybe autovectorization is good enough.
pixel.a = 0xff;
}
}
}

/// Multiply pixel color components by the alpha component.
#[inline]
pub fn premultiply_pixels(&mut self) {
for row in self.pixel_rows() {
for pixel in row {
// TODO: SIMD-optimize this somehow? Or maybe autovectorization is good enough.
let a = pixel.a;
pixel.r = convert::premultiply(pixel.r, a);
pixel.g = convert::premultiply(pixel.g, a);
pixel.b = convert::premultiply(pixel.b, a);
}
}
}

/// Divide pixel color components by the alpha component.
#[inline]
pub fn unpremultiply_pixels(&mut self) {
for row in self.pixel_rows() {
for pixel in row {
// TODO: SIMD-optimize this somehow? Or maybe autovectorization is good enough.
let a = pixel.a;
pixel.r = convert::unpremultiply(pixel.r, a);
pixel.g = convert::unpremultiply(pixel.g, a);
pixel.b = convert::unpremultiply(pixel.b, a);
}
}
}
}

/// Specifies how the alpha channel of the surface should be handled by the compositor.
Expand Down
Loading