mirror of
https://github.com/jhbruhn/catprint-rs.git
synced 2025-03-14 18:35:49 +00:00
Support control over compression
Add a CLI option to allow compression to be disabled--useful for unknown devices that don't support it. Also disables compression by default for devices that are known not to support it.
This commit is contained in:
parent
2f379d2c81
commit
2b460a3956
3 changed files with 86 additions and 42 deletions
|
@ -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(
|
||||
|
|
|
@ -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<u8>,
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
109
src/image.rs
109
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::<u8>::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::<u8>::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<Command> {
|
||||
pub fn print(
|
||||
&self,
|
||||
mode: DrawingMode,
|
||||
quality: Quality,
|
||||
energy: u16,
|
||||
use_compression: bool,
|
||||
) -> Vec<Command> {
|
||||
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));
|
||||
|
|
Loading…
Reference in a new issue