diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs
index c560d21..c93092a 100644
--- a/examples/game_of_life/src/main.rs
+++ b/examples/game_of_life/src/main.rs
@@ -4,7 +4,7 @@ use std::time::Duration;
use clap::Parser;
use rand::{distributions, Rng};
-use servicepoint2::{Command, Connection, Origin, PixelGrid};
+use servicepoint2::{Command, CompressionCode, Connection, Origin, PixelGrid};
#[derive(Parser, Debug)]
struct Cli {
@@ -23,7 +23,7 @@ fn main() {
loop {
connection
- .send(Command::BitmapLinearWin(Origin::top_left(), field.clone()).into())
+ .send(Command::BitmapLinearWin(Origin::top_left(), field.clone(), CompressionCode::Bzip2).into())
.expect("could not send");
thread::sleep(Duration::from_millis(30));
field = iteration(field);
@@ -36,6 +36,7 @@ fn iteration(field: PixelGrid) -> PixelGrid {
for y in 0..field.height {
let old_state = field.get(x, y);
let neighbors = count_neighbors(&field, x as i32, y as i32);
+
let new_state = matches!((old_state, neighbors), (true, 2) | (true, 3) | (false, 3));
next.set(x, y, new_state);
}
diff --git a/examples/moving_line/src/main.rs b/examples/moving_line/src/main.rs
index 5a7ee42..b42962d 100644
--- a/examples/moving_line/src/main.rs
+++ b/examples/moving_line/src/main.rs
@@ -3,7 +3,7 @@ use std::time::Duration;
use clap::Parser;
-use servicepoint2::{Command, Connection, Origin, PIXEL_HEIGHT, PIXEL_WIDTH, PixelGrid};
+use servicepoint2::{Command, CompressionCode, Connection, Origin, PIXEL_HEIGHT, PIXEL_WIDTH, PixelGrid};
#[derive(Parser, Debug)]
struct Cli {
@@ -24,7 +24,7 @@ fn main() {
pixels.set((y + x_offset) % PIXEL_WIDTH as usize, y, true);
}
connection
- .send(Command::BitmapLinearWin(Origin::top_left(), pixels.clone()).into())
+ .send(Command::BitmapLinearWin(Origin::top_left(), pixels.clone(), CompressionCode::Lzma).into())
.unwrap();
thread::sleep(Duration::from_millis(14));
}
diff --git a/examples/random_brightness/src/main.rs b/examples/random_brightness/src/main.rs
index e764036..eff7a25 100644
--- a/examples/random_brightness/src/main.rs
+++ b/examples/random_brightness/src/main.rs
@@ -4,9 +4,7 @@ use clap::Parser;
use rand::Rng;
use servicepoint2::Command::{BitmapLinearWin, Brightness, CharBrightness};
-use servicepoint2::{
- ByteGrid, Connection, Origin, PixelGrid, TILE_HEIGHT, TILE_WIDTH,
-};
+use servicepoint2::{ByteGrid, CompressionCode, Connection, Origin, PixelGrid, TILE_HEIGHT, TILE_WIDTH};
#[derive(Parser, Debug)]
struct Cli {
@@ -30,7 +28,7 @@ fn main() {
let mut filled_grid = PixelGrid::max_sized();
filled_grid.fill(true);
connection
- .send(BitmapLinearWin(Origin::top_left(), filled_grid).into())
+ .send(BitmapLinearWin(Origin::top_left(), filled_grid, CompressionCode::Lzma).into())
.unwrap();
}
diff --git a/examples/wiping_clear/src/main.rs b/examples/wiping_clear/src/main.rs
index bec8385..d27492f 100644
--- a/examples/wiping_clear/src/main.rs
+++ b/examples/wiping_clear/src/main.rs
@@ -3,7 +3,7 @@ use std::time::Duration;
use clap::Parser;
-use servicepoint2::{BitVec, Command, CompressionCode, Connection, Origin, PIXEL_HEIGHT, PIXEL_WIDTH, PixelGrid};
+use servicepoint2::{BitVec, Command, CompressionCode, Connection, PIXEL_HEIGHT, PIXEL_WIDTH, PixelGrid};
#[derive(Parser, Debug)]
struct Cli {
@@ -16,16 +16,10 @@ struct Cli {
fn main() {
env_logger::init();
let cli = Cli::parse();
+ let sleep_duration = Duration::from_millis(cli.time / PIXEL_WIDTH as u64);
let connection = Connection::open(cli.destination).unwrap();
- let mut buf = PixelGrid::max_sized();
- buf.fill(true);
- connection.send(Command::BitmapLinearWin(Origin(0, 0), buf).into())
- .expect("send failed");
-
- let sleep_duration = Duration::from_millis(cli.time / PIXEL_WIDTH as u64);
-
let mut enabled_pixels =
PixelGrid::new(PIXEL_WIDTH as usize, PIXEL_HEIGHT as usize);
enabled_pixels.fill(true);
diff --git a/servicepoint2-binding-c/servicepoint2.h b/servicepoint2-binding-c/servicepoint2.h
index 717bf35..3d606f9 100644
--- a/servicepoint2-binding-c/servicepoint2.h
+++ b/servicepoint2-binding-c/servicepoint2.h
@@ -284,7 +284,8 @@ struct sp2_Command *sp2_command_bitmap_linear_or(sp2_Offset offset,
*/
struct sp2_Command *sp2_command_bitmap_linear_win(uint16_t x,
uint16_t y,
- struct sp2_PixelGrid *byte_grid);
+ struct sp2_PixelGrid *byte_grid,
+ sp2_CompressionCode compression_code);
/**
* Allocates a new `Command::BitmapLinearXor` instance.
diff --git a/servicepoint2-binding-cs/src/BindGen/ServicePoint2.g.cs b/servicepoint2-binding-cs/src/BindGen/ServicePoint2.g.cs
index f4e3d53..2fb4fef 100644
--- a/servicepoint2-binding-cs/src/BindGen/ServicePoint2.g.cs
+++ b/servicepoint2-binding-cs/src/BindGen/ServicePoint2.g.cs
@@ -149,7 +149,7 @@ namespace ServicePoint2.BindGen
/// Allocates a new `Command::BitmapLinearWin` instance. The passed `PixelGrid` gets deallocated in the process.
[DllImport(__DllName, EntryPoint = "sp2_command_bitmap_linear_win", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
- public static extern Command* sp2_command_bitmap_linear_win(ushort x, ushort y, PixelGrid* byte_grid);
+ public static extern Command* sp2_command_bitmap_linear_win(ushort x, ushort y, PixelGrid* byte_grid, CompressionCode compression_code);
/// Deallocates a `Command`. Note that connection_send does this implicitly, so you only need to do this if you use the library for parsing commands.
[DllImport(__DllName, EntryPoint = "sp2_command_dealloc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
diff --git a/servicepoint2/src/command.rs b/servicepoint2/src/command.rs
index 4b7b2fe..1a9e2d0 100644
--- a/servicepoint2/src/command.rs
+++ b/servicepoint2/src/command.rs
@@ -1,7 +1,4 @@
-use crate::{
- BitVec, ByteGrid, CompressionCode, Header, Packet, PixelGrid,
- TILE_SIZE,
-};
+use crate::{BitVec, ByteGrid, CompressionCode, Header, Packet, PixelGrid, TILE_SIZE};
use crate::command_code::CommandCode;
use crate::compression::{into_compressed, into_decompressed};
@@ -56,7 +53,7 @@ pub enum Command {
/// Show text on the screen. Note that the byte data has to be CP437 encoded.
Cp437Data(Origin, ByteGrid),
/// Sets a window of pixels to the specified values
- BitmapLinearWin(Origin, PixelGrid),
+ BitmapLinearWin(Origin, PixelGrid, CompressionCode),
}
impl From for Packet {
@@ -85,18 +82,25 @@ impl From for Packet {
),
vec![brightness],
),
- Command::BitmapLinearWin(Origin(pixel_x, pixel_y), pixels) => {
+ Command::BitmapLinearWin(Origin(pixel_x, pixel_y), pixels, compression) => {
debug_assert_eq!(pixel_x % 8, 0);
debug_assert_eq!(pixels.width % 8, 0);
+
+ let tile_x = pixel_x / TILE_SIZE;
+ let tile_w = pixels.width as u16 / TILE_SIZE;
+ let pixel_h = pixels.height as u16;
+ let payload = into_compressed(compression, pixels.into());
+ let command = match compression {
+ CompressionCode::Uncompressed => CommandCode::BitmapLinearWinUncompressed,
+ CompressionCode::Zlib => CommandCode::BitmapLinearWinZlib,
+ CompressionCode::Bzip2 => CommandCode::BitmapLinearWinBzip2,
+ CompressionCode::Lzma => CommandCode::BitmapLinearWinLzma,
+ CompressionCode::Zstd => CommandCode::BitmapLinearWinZstd,
+ };
+
Packet(
- Header(
- CommandCode::BitmapLinearWin.into(),
- pixel_x / TILE_SIZE,
- pixel_y,
- pixels.width as u16 / TILE_SIZE,
- pixels.height as u16,
- ),
- pixels.into(),
+ Header(command.into(), tile_x, pixel_y, tile_w, pixel_h),
+ payload,
)
}
Command::BitmapLinear(offset, bits, compression) => {
@@ -160,8 +164,8 @@ impl TryFrom for Command {
type Error = TryFromPacketError;
/// Try to interpret the `Packet` as one containing a `Command`
- fn try_from(value: Packet) -> Result {
- let Packet(Header(command_u16, a, b, c, d), _) = value;
+ fn try_from(packet: Packet) -> Result {
+ let Packet(Header(command_u16, a, b, c, d), _) = packet;
let command_code = match CommandCode::try_from(command_u16) {
Err(_) => {
return Err(TryFromPacketError::InvalidCommand(command_u16));
@@ -170,12 +174,12 @@ impl TryFrom for Command {
};
match command_code {
- CommandCode::Clear => match check_command_only(value) {
+ CommandCode::Clear => match check_command_only(packet) {
Some(err) => Err(err),
None => Ok(Command::Clear),
},
CommandCode::Brightness => {
- let Packet(header, payload) = value;
+ let Packet(header, payload) = packet;
if payload.len() != 1 {
return Err(TryFromPacketError::UnexpectedPayloadSize(
1,
@@ -190,23 +194,23 @@ impl TryFrom for Command {
Ok(Command::Brightness(payload[0]))
}
}
- CommandCode::HardReset => match check_command_only(value) {
+ CommandCode::HardReset => match check_command_only(packet) {
Some(err) => Err(err),
None => Ok(Command::HardReset),
},
- CommandCode::FadeOut => match check_command_only(value) {
+ CommandCode::FadeOut => match check_command_only(packet) {
Some(err) => Err(err),
None => Ok(Command::FadeOut),
},
CommandCode::Cp437Data => {
- let Packet(_, payload) = value;
+ let Packet(_, payload) = packet;
Ok(Command::Cp437Data(
Origin(a, b),
ByteGrid::load(c as usize, d as usize, &payload),
))
}
CommandCode::CharBrightness => {
- let Packet(_, payload) = value;
+ let Packet(_, payload) = packet;
Ok(Command::CharBrightness(
Origin(a, b),
ByteGrid::load(c as usize, d as usize, &payload),
@@ -214,37 +218,60 @@ impl TryFrom for Command {
}
#[allow(deprecated)]
CommandCode::BitmapLegacy => Ok(Command::BitmapLegacy),
- CommandCode::BitmapLinearWin => {
- let Packet(_, payload) = value;
- Ok(Command::BitmapLinearWin(
- Origin(a * TILE_SIZE, b),
- PixelGrid::load(
- c as usize * TILE_SIZE as usize,
- d as usize,
- &payload,
- ),
- ))
- }
CommandCode::BitmapLinear => {
- let (vec, compression) = packet_into_linear_bitmap(value)?;
+ let (vec, compression) = packet_into_linear_bitmap(packet)?;
Ok(Command::BitmapLinear(a, vec, compression))
}
CommandCode::BitmapLinearAnd => {
- let (vec, compression) = packet_into_linear_bitmap(value)?;
+ let (vec, compression) = packet_into_linear_bitmap(packet)?;
Ok(Command::BitmapLinearAnd(a, vec, compression))
}
CommandCode::BitmapLinearOr => {
- let (vec, compression) = packet_into_linear_bitmap(value)?;
+ let (vec, compression) = packet_into_linear_bitmap(packet)?;
Ok(Command::BitmapLinearOr(a, vec, compression))
}
CommandCode::BitmapLinearXor => {
- let (vec, compression) = packet_into_linear_bitmap(value)?;
+ let (vec, compression) = packet_into_linear_bitmap(packet)?;
Ok(Command::BitmapLinearXor(a, vec, compression))
}
+ CommandCode::BitmapLinearWinUncompressed => {
+ packet_into_bitmap_win(packet, CompressionCode::Uncompressed)
+ }
+ CommandCode::BitmapLinearWinZlib => {
+ packet_into_bitmap_win(packet, CompressionCode::Zlib)
+ }
+ CommandCode::BitmapLinearWinBzip2 => {
+ packet_into_bitmap_win(packet, CompressionCode::Bzip2)
+ }
+ CommandCode::BitmapLinearWinLzma => {
+ packet_into_bitmap_win(packet, CompressionCode::Lzma)
+ }
+ CommandCode::BitmapLinearWinZstd => {
+ packet_into_bitmap_win(packet, CompressionCode::Zstd)
+ }
}
}
}
+fn packet_into_bitmap_win(packet: Packet, compression: CompressionCode) -> Result {
+ let Packet(Header(_, tiles_x, pixels_y, tile_w, pixel_h), payload) = packet;
+
+ let payload = match into_decompressed(compression, payload) {
+ None => return Err(TryFromPacketError::DecompressionFailed),
+ Some(decompressed) => decompressed,
+ };
+
+ Ok(Command::BitmapLinearWin(
+ Origin(tiles_x * TILE_SIZE, pixels_y),
+ PixelGrid::load(
+ tile_w as usize * TILE_SIZE as usize,
+ pixel_h as usize,
+ &payload,
+ ),
+ CompressionCode::Uncompressed,
+ ))
+}
+
/// Helper method for BitMapLinear*-Commands into Packet
fn bitmap_linear_into_packet(
command: CommandCode,
@@ -315,7 +342,6 @@ pub mod c_api
use crate::{BitVec, Brightness, ByteGrid, Command, CompressionCode, Offset, Origin, Packet, PixelGrid};
-
/// Tries to turn a `Packet` into a `Command`. The packet is gets deallocated in the process.
///
/// Returns: pointer to command or NULL
@@ -409,9 +435,9 @@ pub mod c_api
/// Allocates a new `Command::BitmapLinearWin` instance.
/// The passed `PixelGrid` gets deallocated in the process.
#[no_mangle]
- pub unsafe extern "C" fn sp2_command_bitmap_linear_win(x: u16, y: u16, byte_grid: *mut PixelGrid) -> *mut Command {
+ pub unsafe extern "C" fn sp2_command_bitmap_linear_win(x: u16, y: u16, byte_grid: *mut PixelGrid, compression_code: CompressionCode) -> *mut Command {
let byte_grid = *Box::from_raw(byte_grid);
- Box::into_raw(Box::new(Command::BitmapLinearWin(Origin(x, y), byte_grid)))
+ Box::into_raw(Box::new(Command::BitmapLinearWin(Origin(x, y), byte_grid, compression_code)))
}
/// Deallocates a `Command`. Note that connection_send does this implicitly, so you only need
diff --git a/servicepoint2/src/command_code.rs b/servicepoint2/src/command_code.rs
index 4c77a23..0331573 100644
--- a/servicepoint2/src/command_code.rs
+++ b/servicepoint2/src/command_code.rs
@@ -11,10 +11,14 @@ pub(crate) enum CommandCode {
#[deprecated]
BitmapLegacy = 0x0010,
BitmapLinear = 0x0012,
- BitmapLinearWin = 0x0013,
+ BitmapLinearWinUncompressed = 0x0013,
BitmapLinearAnd = 0x0014,
BitmapLinearOr = 0x0015,
BitmapLinearXor = 0x0016,
+ BitmapLinearWinZlib = 0x0017,
+ BitmapLinearWinBzip2 = 0x0018,
+ BitmapLinearWinLzma = 0x0019,
+ BitmapLinearWinZstd = 0x001A,
}
impl From for u16 {
@@ -41,7 +45,7 @@ impl TryFrom for CommandCode {
#[allow(deprecated)]
value if value == BitmapLegacy as u16 => Ok(BitmapLegacy),
value if value == BitmapLinear as u16 => Ok(BitmapLinear),
- value if value == BitmapLinearWin as u16 => Ok(BitmapLinearWin),
+ value if value == BitmapLinearWinUncompressed as u16 => Ok(BitmapLinearWinUncompressed),
value if value == BitmapLinearAnd as u16 => Ok(BitmapLinearAnd),
value if value == BitmapLinearOr as u16 => Ok(BitmapLinearOr),
value if value == BitmapLinearXor as u16 => Ok(BitmapLinearXor),