correct the pixel shifts — the stream was cyan, not grey
SetPixelFormat asked for 32bpp big-endian with shifts 16/8/0, which is the pixel 0x00RRGGBB and puts X,R,G,B on the wire. The Raw path copies four bytes straight into ImageData and forces alpha opaque, so every channel landed one place along and blue was dropped: window grey rendered cyan, the red LED digits rendered green, blue "1" cells and the title bar rendered black. Shifts are now 24/16/8, making the pixel 0xRRGGBB00 and the wire R,G,B,X — which is what the file already claimed, in two comments, since it was written. Verified against the live x11vnc socket rather than by reading: probing the same framebuffer under both formats returns `00 c0 c0 c0` for window grey with the old shifts and `c0 c0 c0 00` with the new ones, and `00 ff 00 00` vs `ff 00 00 00` for the digits. x11vnc honours a shift of 24 without complaint. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Officer-Session: de3ed4e6-f88a-429c-94e6-a760336ba83b
This commit is contained in:
+13
-7
@@ -16,9 +16,15 @@
|
|||||||
* ── The pixel format ──
|
* ── The pixel format ──
|
||||||
*
|
*
|
||||||
* The client DICTATES the format via SetPixelFormat rather than accepting the server's, so decoding is
|
* The client DICTATES the format via SetPixelFormat rather than accepting the server's, so decoding is
|
||||||
* a memcpy into ImageData instead of a per-pixel shift-and-mask. We ask for 32bpp true colour with
|
* a memcpy into ImageData instead of a per-pixel shift-and-mask. We ask for 32bpp true colour,
|
||||||
* big-endian byte order, which puts the bytes on the wire as R,G,B,X — exactly the order a canvas
|
* big-endian, with red/green/blue shifts of 24/16/8. That makes the pixel value 0xRRGGBB00, which
|
||||||
* ImageData buffer wants, so a Raw rectangle copies straight in.
|
* big-endian puts on the wire as R,G,B,X — exactly the order a canvas ImageData buffer wants, so a Raw
|
||||||
|
* rectangle copies straight in.
|
||||||
|
*
|
||||||
|
* The shifts are the load-bearing part, and 16/8/0 is the tempting wrong answer: it is the familiar
|
||||||
|
* 0x00RRGGBB, and big-endian then sends X,R,G,B. Copied into ImageData that moves every channel one
|
||||||
|
* place along and drops blue — grey renders cyan, red renders green, blue renders black. The first
|
||||||
|
* alpha shipped that way, with this comment already claiming otherwise.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export type RfbEvents = {
|
export type RfbEvents = {
|
||||||
@@ -190,7 +196,7 @@ export class RfbClient {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 32bpp true colour, big-endian, shifts 16/8/0 — i.e. R,G,B,X on the wire, which is ImageData order. */
|
/** 32bpp true colour, big-endian, shifts 24/16/8 — i.e. R,G,B,X on the wire, which is ImageData order. */
|
||||||
private setPixelFormat(): void {
|
private setPixelFormat(): void {
|
||||||
const message = new Uint8Array(20);
|
const message = new Uint8Array(20);
|
||||||
const view = new DataView(message.buffer);
|
const view = new DataView(message.buffer);
|
||||||
@@ -202,9 +208,9 @@ export class RfbClient {
|
|||||||
view.setUint16(8, 255); // red max
|
view.setUint16(8, 255); // red max
|
||||||
view.setUint16(10, 255); // green max
|
view.setUint16(10, 255); // green max
|
||||||
view.setUint16(12, 255); // blue max
|
view.setUint16(12, 255); // blue max
|
||||||
message[14] = 16; // red shift
|
message[14] = 24; // red shift
|
||||||
message[15] = 8; // green shift
|
message[15] = 16; // green shift
|
||||||
message[16] = 0; // blue shift
|
message[16] = 8; // blue shift
|
||||||
this.send(message);
|
this.send(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user