diff --git a/README.md b/README.md index 2948de5..ae088c1 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,12 @@ It claims to be the fastest Pixelflut server in existence - at least at the time # Available Pixelflut commands Commands must be sent newline-separated, for more details see [Pixelflut](https://wiki.cccgoe.de/wiki/Pixelflut) * `HELP`: Prints a help text with the available commands. -* `PX x y rrggbb`: Color the pixel (x,y) with the given hexadecimal color, e.g. `PX 10 10 ff0000` +* `PX x y rrggbb`: PX x y rrggbb: Color the pixel (x,y) with the given hexadecimal color rrggbb, e.g. `PX 10 10 ff0000` * `PX x y rrggbbaa`: Color the pixel (x,y) with the given hexadecimal color rrggbb (alpha channel is ignored for now), e.g. `PX 10 10 ff0000ff` +* `PX x y gg`: Color the pixel (x,y) with the hexadecimal color gggggg. Basically this is the same as the other commands, but is a more efficient way of filling white, black or gray areas, e.g. `PX 10 10 00` to paint black * `PX x y`: Get the color value of the pixel (x,y), e.g. `PX 10 10` * `SIZE`: Get the size of the drawing surface, e.g. `SIZE 1920 1080` -* `OFFSET x y`: Apply offset (x,y) to all further pixel draws on this connection +* `OFFSET x y`: Apply offset (x,y) to all further pixel draws on this connection. This can e.g. be used to pre-calculate an image/animation and simply use the OFFSET command to move it around the screen without the need to re-calculate it, e.g. `OFFSET 100 100` # Usage The easiest way is to continue with the provided [Ready to use Docker setup](#run-in-docker-container) below. diff --git a/src/network.rs b/src/network.rs index 55fabcb..20ff984 100644 --- a/src/network.rs +++ b/src/network.rs @@ -241,6 +241,11 @@ mod test { #[case("PX 0 0 abcdefaa\nPX 0 0\n", "PX 0 0 abcdef\n")] #[case("PX 0 1 abcdefaa\nPX 0 1\n", "PX 0 1 abcdef\n")] #[case("PX 1 0 abcdefaa\nPX 1 0\n", "PX 1 0 abcdef\n")] + // Short commands + #[case("PX 0 0 00\nPX 0 0\n", "PX 0 0 000000\n")] + #[case("PX 0 0 ff\nPX 0 0\n", "PX 0 0 ffffff\n")] + #[case("PX 0 1 12\nPX 0 1\n", "PX 0 1 121212\n")] + #[case("PX 0 1 34\nPX 0 1\n", "PX 0 1 343434\n")] // Tests invalid bounds #[case("PX 9999 0 abcdef\nPX 9999 0\n", "")] // Parsable but outside screen size #[case("PX 0 9999 abcdef\nPX 9999 0\n", "")] diff --git a/src/parser.rs b/src/parser.rs index 4ce0928..7643c56 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -9,11 +9,12 @@ pub const HELP_TEXT: &[u8] = "\ Pixelflut server powered by breakwater https://github.com/sbernauer/breakwater Available commands: HELP: Show this help -PX x y rrggbb: Color the pixel (x,y) with the given hexadecimal color +PX x y rrggbb: Color the pixel (x,y) with the given hexadecimal color rrggbb PX x y rrggbbaa: Color the pixel (x,y) with the given hexadecimal color rrggbb (alpha channel is ignored for now) +PX x y gg: Color the pixel (x,y) with the hexadecimal color gggggg. Basically this is the same as the other commands, but is a more efficient way of filling white, black or gray areas PX x y: Get the color value of the pixel (x,y) SIZE: Get the size of the drawing surface, e.g. `SIZE 1920 1080` -OFFSET x y: Apply offset (x,y) to all further pixel draws on this connection +OFFSET x y: Apply offset (x,y) to all further pixel draws on this connection. This can e.g. be used to pre-calculate an image/animation and simply use the OFFSET command to move it around the screen without the need to re-calculate it ".as_bytes(); #[derive(Clone, Default, Debug)] @@ -120,7 +121,7 @@ pub async fn parse_pixelflut_commands( if buffer[i] == b' ' { i += 1; - // TODO: Determine what clients use more: RGB or RGBA. + // TODO: Determine what clients use more: RGB, RGBA or gg variant. // If RGBA is used more often move the RGB code below the RGBA code // Must be followed by 6 bytes RGB and newline or ... @@ -177,6 +178,31 @@ pub async fn parse_pixelflut_commands( continue; } + + // ... for the efficient/lazy clients + if buffer[i + 2] == b'\n' { + last_byte_parsed = i + 2; + i += 3; // We can advance one byte more than normal as we use continue and therefore not get incremented at the end of the loop + + let rgba: u32 = + (ASCII_HEXADECIMAL_VALUES[buffer[i - 3] as usize] as u32) << 20 + | (ASCII_HEXADECIMAL_VALUES[buffer[i - 2] as usize] as u32) + << 16 + | (ASCII_HEXADECIMAL_VALUES[buffer[i - 3] as usize] as u32) + << 12 + | (ASCII_HEXADECIMAL_VALUES[buffer[i - 2] as usize] as u32) + << 8 + | (ASCII_HEXADECIMAL_VALUES[buffer[i - 3] as usize] as u32) + << 4 + | (ASCII_HEXADECIMAL_VALUES[buffer[i - 2] as usize] as u32); + + fb.set(x, y, rgba); + if cfg!(feature = "count_pixels") { + // statistics.inc_pixels(ip); + } + + continue; + } } // End of command to read Pixel value