diff --git a/src/bin/catprint.rs b/src/bin/catprint.rs index 5359fb9..92324ba 100644 --- a/src/bin/catprint.rs +++ b/src/bin/catprint.rs @@ -45,6 +45,10 @@ struct Print { /// Rotate picture by 90 degrees #[clap(short, long)] rotate: bool, + + /// Don't use compression + #[clap(long)] + no_compress: bool, } #[derive(ArgEnum)] @@ -112,7 +116,8 @@ async fn main_print(mut device: device::Device, print: Print) -> Result<(), Box< _ => protocol::DrawingMode::Image, }; - let print = image.print(mode, quality, energy); + let use_compression = device.supports_compression() && !print.no_compress; + let print = image.print(mode, quality, energy, use_compression); device.queue_commands(&print); device.queue_command(protocol::Command::Feed( diff --git a/src/device.rs b/src/device.rs index f85cd52..481a6f6 100644 --- a/src/device.rs +++ b/src/device.rs @@ -11,6 +11,7 @@ const TX_CHARACTERISTIC_UUID: Uuid = Uuid::from_u128(0x0000ae01_0000_1000_8000_0 #[derive(Debug)] pub struct Device { peripheral: btleplug::platform::Peripheral, + supports_compression: bool, tx_buffer: VecDeque, } @@ -41,9 +42,16 @@ impl Device { peripheral.connect().await?; } let _ = peripheral.discover_characteristics().await?; + + let supports_compression = match name { + "MX10" => false, + _ => true, + }; + device_result = Ok(Device { peripheral, tx_buffer: VecDeque::new(), + supports_compression, }); break; } @@ -109,4 +117,8 @@ impl Device { pub async fn destroy(self) { self.peripheral.disconnect().await.unwrap(); } + + pub fn supports_compression(&self) -> bool { + self.supports_compression + } } diff --git a/src/image.rs b/src/image.rs index fa85cb0..876a83e 100644 --- a/src/image.rs +++ b/src/image.rs @@ -66,55 +66,82 @@ impl Image { pub fn line( &self, y: u32, + use_compression: bool, ) -> Option<(bool, usize, [u8; crate::protocol::PIXELS_PER_LINE / 8])> { if y > self.image.height() { - None - } else { - let mut compressed = Vec::::new(); - - let mut counter = 0_u32; - let mut last_val = 2; - for x in 0..crate::protocol::PIXELS_PER_LINE { - let x = x as u32; - let pixel = self.image.get((x, y)).unwrap(); - let val = if pixel > &self.mean { 0 } else { 1 }; - if val == last_val { - counter = counter + 1 - } else if counter > 0 { - compressed.extend(rle_bytes(last_val, counter)); - counter = 1; - } - last_val = val; - } - compressed.extend(rle_bytes(last_val, counter)); - - if compressed.len() > crate::protocol::PIXELS_PER_LINE / 8 { - let mut data = [0_u8; crate::protocol::PIXELS_PER_LINE / 8]; - for x in 0..crate::protocol::PIXELS_PER_LINE { - let x = x as u32; - let pixel = self.image.get((x, y)).unwrap(); - let val = if pixel > &self.mean { 0 } else { 1 }; - let i = (x / 8) as usize; - let j = x % 8; - let current = data[i]; - data[i] = current | (val << j); - } - - Some((false, crate::protocol::PIXELS_PER_LINE / 8, data)) - } else { - use std::convert::TryInto; - let len = compressed.len(); - compressed.resize(crate::protocol::PIXELS_PER_LINE / 8, 0); - Some((true, len, compressed.try_into().unwrap())) - } + return None; } + + if use_compression { + self.line_compressed(y) + } else { + self.line_uncompressed(y) + .map(|(len, data)| (false, len, data)) + } + } + + pub fn line_compressed( + &self, + y: u32, + ) -> Option<(bool, usize, [u8; crate::protocol::PIXELS_PER_LINE / 8])> { + let mut compressed = Vec::::new(); + + let mut counter = 0_u32; + let mut last_val = 2; + for x in 0..crate::protocol::PIXELS_PER_LINE { + let x = x as u32; + let pixel = self.image.get((x, y)).unwrap(); + let val = if pixel > &self.mean { 0 } else { 1 }; + if val == last_val { + counter = counter + 1 + } else if counter > 0 { + compressed.extend(rle_bytes(last_val, counter)); + counter = 1; + } + last_val = val; + } + compressed.extend(rle_bytes(last_val, counter)); + + if compressed.len() > crate::protocol::PIXELS_PER_LINE / 8 { + self.line_uncompressed(y) + .map(|(len, data)| (false, len, data)) + } else { + use std::convert::TryInto; + let len = compressed.len(); + compressed.resize(crate::protocol::PIXELS_PER_LINE / 8, 0); + Some((true, len, compressed.try_into().unwrap())) + } + } + + pub fn line_uncompressed( + &self, + y: u32, + ) -> Option<(usize, [u8; crate::protocol::PIXELS_PER_LINE / 8])> { + let mut data = [0_u8; crate::protocol::PIXELS_PER_LINE / 8]; + for x in 0..crate::protocol::PIXELS_PER_LINE { + let x = x as u32; + let pixel = self.image.get((x, y)).unwrap(); + let val = if pixel > &self.mean { 0 } else { 1 }; + let i = (x / 8) as usize; + let j = x % 8; + let current = data[i]; + data[i] = current | (val << j); + } + + Some((crate::protocol::PIXELS_PER_LINE / 8, data)) } pub fn line_count(&self) -> u32 { self.image.height() } - pub fn print(&self, mode: DrawingMode, quality: Quality, energy: u16) -> Vec { + pub fn print( + &self, + mode: DrawingMode, + quality: Quality, + energy: u16, + use_compression: bool, + ) -> Vec { let mut commands = vec![ Command::SetQuality(quality), Command::SetEnergy(energy), @@ -123,7 +150,7 @@ impl Image { commands.push(Command::MagicLattice(LatticeType::Start)); for y in 0..self.line_count() { - let (compressed, len, pixels) = self.line(y).unwrap(); + let (compressed, len, pixels) = self.line(y, use_compression).unwrap(); commands.push(Command::Print(compressed, len, pixels)); } commands.push(Command::MagicLattice(LatticeType::End));