@@ -225,13 +225,22 @@ impl Drop for ShmCapture { |
| 225 | 225 | /// This is necessary because X11 returns pixels in BGRA format, but most |
| 226 | 226 | /// image formats expect RGBA. |
| 227 | 227 | 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> { |
| 228 | 237 | let mut rgba = Vec::with_capacity(data.len()); |
| 229 | 238 | |
| 230 | 239 | for chunk in data.chunks_exact(4) { |
| 231 | 240 | rgba.push(chunk[2]); // R (was B) |
| 232 | 241 | rgba.push(chunk[1]); // G |
| 233 | 242 | rgba.push(chunk[0]); // B (was R) |
| 234 | | - rgba.push(chunk[3]); // A |
| 243 | + rgba.push(if force_opaque { 255 } else { chunk[3] }); // A |
| 235 | 244 | } |
| 236 | 245 | |
| 237 | 246 | rgba |
@@ -239,8 +248,16 @@ pub fn bgra_to_rgba(data: &[u8]) -> Vec<u8> { |
| 239 | 248 | |
| 240 | 249 | /// Convert BGRA pixel data to RGBA in place. |
| 241 | 250 | 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) { |
| 242 | 256 | for chunk in data.chunks_exact_mut(4) { |
| 243 | 257 | chunk.swap(0, 2); // Swap B and R |
| 258 | + if force_opaque { |
| 259 | + chunk[3] = 255; |
| 260 | + } |
| 244 | 261 | } |
| 245 | 262 | } |
| 246 | 263 | |