Fix screenshot byte order conversion (critical bug)
The conversion functions were producing big-endian ARGB (A,R,G,B) but Cairo's ARGB32 on little-endian systems expects B,G,R,A byte order. This caused screenshots to appear completely corrupted (likely black or solid color). Fixed both convert_xbgr8888_to_argb32 and convert_xrgb8888_to_argb32: - Xbgr8888: source [R,G,B,X] -> dest [B,G,R,A=255] - Xrgb8888: source [B,G,R,X] -> dest [B,G,R,A=255] Added detailed comments explaining memory layouts and conversion logic to prevent future regressions. This should make screenshots display correctly.
This commit is contained in:
+22
-22
@@ -273,34 +273,34 @@ impl ScreenshotManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert Xbgr8888 buffer data to ARGB32 format.
|
/// Convert Xbgr8888 buffer data to ARGB32 format (little-endian byte order).
|
||||||
|
/// Xbgr8888: 32-bit word 0xXXBBGGRR, memory layout: [R, G, B, X]
|
||||||
|
/// ARGB32: 32-bit word 0xAARRGGBB, memory layout: [B, G, R, A]
|
||||||
fn convert_xbgr8888_to_argb32(data: &[u8], width: usize, height: usize) -> Vec<u8> {
|
fn convert_xbgr8888_to_argb32(data: &[u8], width: usize, height: usize) -> Vec<u8> {
|
||||||
let mut result = vec![0u8; width * height * 4];
|
let mut result = Vec::with_capacity(width * height * 4);
|
||||||
for y in 0..height {
|
for i in 0..width * height {
|
||||||
for x in 0..width {
|
let src = i * 4;
|
||||||
let src_idx = (y * width + x) * 4;
|
// Source: [R, G, B, X] -> Destination: [B, G, R, A=255]
|
||||||
let dst_idx = (y * width + x) * 4;
|
result.push(data[src + 2]); // B
|
||||||
result[dst_idx] = 255;
|
result.push(data[src + 1]); // G
|
||||||
result[dst_idx + 1] = data[src_idx + 2];
|
result.push(data[src]); // R
|
||||||
result[dst_idx + 2] = data[src_idx + 1];
|
result.push(255); // A
|
||||||
result[dst_idx + 3] = data[src_idx];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert Xrgb8888 buffer data to ARGB32 format.
|
/// Convert Xrgb8888 buffer data to ARGB32 format (little-endian byte order).
|
||||||
|
/// Xrgb8888: 32-bit word 0xXXRRGGBB, memory layout: [B, G, R, X]
|
||||||
|
/// ARGB32: 32-bit word 0xAARRGGBB, memory layout: [B, G, R, A]
|
||||||
fn convert_xrgb8888_to_argb32(data: &[u8], width: usize, height: usize) -> Vec<u8> {
|
fn convert_xrgb8888_to_argb32(data: &[u8], width: usize, height: usize) -> Vec<u8> {
|
||||||
let mut result = vec![0u8; width * height * 4];
|
let mut result = Vec::with_capacity(width * height * 4);
|
||||||
for y in 0..height {
|
for i in 0..width * height {
|
||||||
for x in 0..width {
|
let src = i * 4;
|
||||||
let src_idx = (y * width + x) * 4;
|
// Source: [B, G, R, X] -> Destination: [B, G, R, A=255]
|
||||||
let dst_idx = (y * width + x) * 4;
|
result.push(data[src]); // B
|
||||||
result[dst_idx] = 255;
|
result.push(data[src + 1]); // G
|
||||||
result[dst_idx + 1] = data[src_idx + 1];
|
result.push(data[src + 2]); // R
|
||||||
result[dst_idx + 2] = data[src_idx + 2];
|
result.push(255); // A
|
||||||
result[dst_idx + 3] = data[src_idx + 3];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user