feat: phase 5 — Tight decoder with zlib streams and sub-palettes
All checks were successful
CI / fmt (push) Successful in 36s
CI / check (push) Successful in 1m1s
CI / clippy (push) Successful in 1m4s

codec/tight.rs:
- Full Tight (encoding 7) decoder per ByteColorRFBRenderer.a() line 324
- Control byte: bottom 4 bits = zlib stream reset flags,
  top 4 bits = subencoding (0-15)
- Subencoding 8: solid fill (1-byte color)
- Subencoding 15: palette-indexed fill (selector + index)
- Subencodings 4-7: filtered data with optional 2-color palette
- Subencodings 10-13: reduced bit-depth packed (1/2/4 bpp)
- Subencodings 0-3: raw 8bpp data
- Data >= 12 bytes uses zlib compression with varint length
- 4 persistent zlib streams with reset-on-flag logic
- All 4 hardcoded sub-palettes ported as RGB332 indices:
  PALETTE_BW (2), PALETTE_GRAY4 (4), PALETTE_GRAY16 (16),
  PALETTE_COLOR16 (16 EGA-like colors)
- Bit-depth unpackers: 1bpp, 2bpp, 4bpp (MSB-first)
- 5 unit tests

Updated examples to request [7, 5, 1, 0, -250] (Tight preferred).
Tested against real OmniView: correct rendering with Tight encoding.
32 tests passing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-06 14:44:06 +03:00
parent 21ed797302
commit c8f981f045
7 changed files with 401 additions and 5 deletions

View File

@@ -1,7 +1,7 @@
use std::io::{BufReader, BufWriter};
use std::net::TcpStream;
use crate::codec::hextile;
use crate::codec::{hextile, tight};
use crate::framebuffer::Framebuffer;
use crate::handshake::{self, Config, ServerInit};
use crate::msg::{self, ServerMsg};
@@ -45,6 +45,7 @@ pub struct ActiveSession {
pub reader: BufReader<TcpStream>,
pub writer: BufWriter<TcpStream>,
pub server_init: ServerInit,
zlib: tight::ZlibStreams,
}
impl ActiveSession {
@@ -57,6 +58,7 @@ impl ActiveSession {
reader: raw.reader,
writer: raw.writer,
server_init: raw.server_init,
zlib: tight::ZlibStreams::new(),
};
// Tell server to send 8bpp RGB332 pixels
@@ -208,6 +210,18 @@ impl ActiveSession {
hdr.h,
)?;
}
7 => {
// Tight
tight::decode_tight(
&mut self.reader,
&mut self.framebuffer,
&mut self.zlib,
hdr.x,
hdr.y,
hdr.w,
hdr.h,
)?;
}
other => {
return Err(SessionError::UnsupportedEncoding(other));
}