fix: keep the alpha of window shots in the preview

This commit is contained in:
elwrcl committed 2026-10-02 16:28:28 +03:00
1 parent 3c24d604eb
commit 1b5d2f082d
1 file changed
+23 -2
+23 -2
View File
@@ -82,8 +82,10 @@ pub fn paint(canvas: &mut [u8], canvas_width: u32, small: &RgbaImage, x0: i64) {
let px = if edge { let px = if edge {
BORDER BORDER
} else { } else {
let [r, g, b, _] = small.get_pixel(x, y).0; // wl_shm's ARGB is premultiplied; window shots have alpha.
[b, g, r, 255] let [r, g, b, a] = small.get_pixel(x, y).0;
let pre = |c: u8| (u16::from(c) * u16::from(a) / 255) as u8;
[pre(b), pre(g), pre(r), a]
}; };
let i = ((y * canvas_width) as usize + cx as usize) * 4; let i = ((y * canvas_width) as usize + cx as usize) * 4;
canvas[i..i + 4].copy_from_slice(&px); canvas[i..i + 4].copy_from_slice(&px);
@@ -591,6 +593,25 @@ mod tests {
assert_eq!(pixel(&canvas, 6, 5, 2), [0; 4]); assert_eq!(pixel(&canvas, 6, 5, 2), [0; 4]);
} }
#[test]
fn paint_keeps_transparency_premultiplied() {
// Window shots have transparent rounded corners and shadows.
let mut img = RgbaImage::from_pixel(4, 3, image::Rgba([0, 0, 0, 0]));
img.put_pixel(2, 1, image::Rgba([255, 100, 0, 128]));
let mut canvas = vec![9u8; 4 * 3 * 4];
paint(&mut canvas, 4, &img, 0);
assert_eq!(
pixel(&canvas, 4, 1, 1),
[0; 4],
"transparent stays transparent"
);
assert_eq!(
pixel(&canvas, 4, 2, 1),
[0, 50, 128, 128],
"premultiplied BGRA"
);
}
#[test] #[test]
fn paint_with_offset_shifts_and_clips() { fn paint_with_offset_shifts_and_clips() {
let mut canvas = vec![0u8; 6 * 3 * 4]; let mut canvas = vec![0u8; 6 * 3 * 4];