gardesk/garshot / 31fc5ea

Browse files

Fix alpha channel for compositor overlay captures

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
31fc5ea07e5ca01c7a5561f5333795d01b66cf78
Parents
dbfb5b1
Tree
12e0d01

4 changed files

StatusFile+-
M garshot/src/capture/region.rs 3 2
M garshot/src/capture/screen.rs 3 2
M garshot/src/selection/overlay.rs 2 1
M garshot/src/x11/shm.rs 18 1
garshot/src/capture/region.rsmodified
@@ -1,7 +1,7 @@
11
 //! Region capture functionality.
22
 
33
 use crate::error::{GarshotError, Result};
4
-use crate::x11::{shm::bgra_to_rgba, Connection, ShmCapture};
4
+use crate::x11::{shm::bgra_to_rgba_with_alpha, Connection, ShmCapture};
55
 
66
 /// A rectangular region on the screen.
77
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -135,7 +135,8 @@ pub fn capture_region(
135135
     );
136136
 
137137
     let data = shm.capture(conn, clipped.x, clipped.y, clipped.width, clipped.height)?;
138
-    let rgba = bgra_to_rgba(data);
138
+    // Force opaque alpha when capturing from compositor overlay (which has alpha=0)
139
+    let rgba = bgra_to_rgba_with_alpha(data, conn.compositor_active);
139140
 
140141
     Ok(RegionCaptureResult {
141142
         data: rgba,
garshot/src/capture/screen.rsmodified
@@ -1,7 +1,7 @@
11
 //! Full screen capture functionality.
22
 
33
 use crate::error::Result;
4
-use crate::x11::{shm::bgra_to_rgba, Connection, ShmCapture};
4
+use crate::x11::{shm::bgra_to_rgba_with_alpha, Connection, ShmCapture};
55
 
66
 /// Capture the full screen.
77
 ///
@@ -10,7 +10,8 @@ pub fn capture_full_screen(conn: &Connection, shm: &ShmCapture) -> Result<Captur
1010
     let data = shm.capture(conn, 0, 0, conn.width, conn.height)?;
1111
 
1212
     // Convert BGRA (X11 format) to RGBA (standard format)
13
-    let rgba = bgra_to_rgba(data);
13
+    // Force opaque alpha when capturing from compositor overlay (which has alpha=0)
14
+    let rgba = bgra_to_rgba_with_alpha(data, conn.compositor_active);
1415
 
1516
     Ok(CaptureResult {
1617
         data: rgba,
garshot/src/selection/overlay.rsmodified
@@ -55,7 +55,8 @@ pub fn interactive_selection(
5555
     // 1. Capture current screen
5656
     let capture_data = shm.capture(conn, 0, 0, conn.width, conn.height)?;
5757
     // Convert BGRA to RGBA and copy to owned buffer
58
-    let original_data = crate::x11::shm::bgra_to_rgba(capture_data);
58
+    // Force opaque alpha when capturing from compositor overlay (which has alpha=0)
59
+    let original_data = crate::x11::shm::bgra_to_rgba_with_alpha(capture_data, conn.compositor_active);
5960
 
6061
     // 2. Apply blur for overlay background
6162
     let mut blurred_data = original_data.clone();
garshot/src/x11/shm.rsmodified
@@ -225,13 +225,22 @@ impl Drop for ShmCapture {
225225
 /// This is necessary because X11 returns pixels in BGRA format, but most
226226
 /// image formats expect RGBA.
227227
 pub fn bgra_to_rgba(data: &[u8]) -> Vec<u8> {
228
+    bgra_to_rgba_with_alpha(data, false)
229
+}
230
+
231
+/// Convert BGRA pixel data (X11 format) to RGBA, optionally forcing opaque alpha.
232
+///
233
+/// When `force_opaque` is true, all alpha values are set to 255. This is needed
234
+/// when capturing from the compositor overlay window, which returns valid RGB
235
+/// data but with alpha=0 (transparent).
236
+pub fn bgra_to_rgba_with_alpha(data: &[u8], force_opaque: bool) -> Vec<u8> {
228237
     let mut rgba = Vec::with_capacity(data.len());
229238
 
230239
     for chunk in data.chunks_exact(4) {
231240
         rgba.push(chunk[2]); // R (was B)
232241
         rgba.push(chunk[1]); // G
233242
         rgba.push(chunk[0]); // B (was R)
234
-        rgba.push(chunk[3]); // A
243
+        rgba.push(if force_opaque { 255 } else { chunk[3] }); // A
235244
     }
236245
 
237246
     rgba
@@ -239,8 +248,16 @@ pub fn bgra_to_rgba(data: &[u8]) -> Vec<u8> {
239248
 
240249
 /// Convert BGRA pixel data to RGBA in place.
241250
 pub fn bgra_to_rgba_inplace(data: &mut [u8]) {
251
+    bgra_to_rgba_inplace_with_alpha(data, false)
252
+}
253
+
254
+/// Convert BGRA pixel data to RGBA in place, optionally forcing opaque alpha.
255
+pub fn bgra_to_rgba_inplace_with_alpha(data: &mut [u8], force_opaque: bool) {
242256
     for chunk in data.chunks_exact_mut(4) {
243257
         chunk.swap(0, 2); // Swap B and R
258
+        if force_opaque {
259
+            chunk[3] = 255;
260
+        }
244261
     }
245262
 }
246263