123 lines
4.2 KiB
Rust
123 lines
4.2 KiB
Rust
use eyre::{bail, Context};
|
|
use labelo_p710bt::commander::P710btCommander;
|
|
use labelo_p710bt::protocol::{AdvancedModeSettings, VariousModeSettings, PIXELS_ON_TAPE_SIZES};
|
|
use labelo_p710bt::usb::UsbP710bt;
|
|
use std::env::args;
|
|
use std::path::Path;
|
|
use tracing::{info, warn};
|
|
use tracing_subscriber::layer::SubscriberExt;
|
|
use tracing_subscriber::util::SubscriberInitExt;
|
|
|
|
pub fn main() -> eyre::Result<()> {
|
|
tracing_subscriber::registry()
|
|
.with(
|
|
tracing_subscriber::EnvFilter::try_from_default_env()
|
|
.unwrap_or_else(|_| "p710bt=debug,info".into()),
|
|
)
|
|
.with(tracing_subscriber::fmt::layer())
|
|
.init();
|
|
|
|
let mut images = Vec::new();
|
|
|
|
for arg in args().skip(1) {
|
|
let image_path = Path::new(&arg);
|
|
let image = image::open(image_path)
|
|
.with_context(|| format!("failed to load image {image_path:?}"))?;
|
|
images.push(image.into_rgba8());
|
|
}
|
|
|
|
let mut devices = UsbP710bt::list_devices()?;
|
|
|
|
if devices.len() != 1 {
|
|
bail!("Found {} P710BT devices, aborting.", devices.len());
|
|
}
|
|
|
|
let device = UsbP710bt::open(devices.remove(0))?;
|
|
let mut printer = P710btCommander::new(device)?;
|
|
|
|
printer.invalidate_and_initialise()?;
|
|
let status = printer.status()?;
|
|
info!("Printer status: {status:?}");
|
|
|
|
let media_width_mm = status.media_width_mm as u32;
|
|
if media_width_mm == 0 {
|
|
bail!("Media width is 0; is there tape loaded?");
|
|
}
|
|
|
|
let Some(media_width_info) = PIXELS_ON_TAPE_SIZES.iter().find(|info| info.mm == media_width_mm) else {
|
|
bail!("Unrecognised tape width: this usually means support is needed in labelo ({media_width_mm} mm).");
|
|
};
|
|
info!("Media width information: {media_width_info:?}");
|
|
|
|
printer.set_raster_mode_and_automatic_notification()?;
|
|
|
|
for (page, image) in images.iter().enumerate() {
|
|
if image.height() > media_width_info.practical_px_limit {
|
|
bail!(
|
|
"Image/page {page} exceeds the practical print height limit of {} px ({} px).",
|
|
media_width_info.practical_px_limit,
|
|
image.height()
|
|
);
|
|
}
|
|
if image.height() > media_width_info.datasheet_px_limit {
|
|
warn!("Image/page {page} is {} px high which exceeds the datasheet print height of {} px but fits within the empirical print height limit of {} px.", image.height(), media_width_info.datasheet_px_limit, media_width_info.practical_px_limit);
|
|
}
|
|
}
|
|
|
|
for page in 0..images.len() {
|
|
let image = &images[page];
|
|
|
|
let lines = image.width();
|
|
|
|
printer
|
|
.print_information(
|
|
status.media_type.unwrap(),
|
|
status.media_width_mm,
|
|
lines,
|
|
page == 0,
|
|
)
|
|
.context("PIC")?;
|
|
|
|
let mut ams = AdvancedModeSettings::NO_BUFFER_CLEARING_WHEN_PRINTING;
|
|
if page == images.len() - 1 {
|
|
// TODO not always desirable, but for testing it is handy to have it cut on the last piece.
|
|
ams |= AdvancedModeSettings::NO_CHAIN_PRINTING;
|
|
}
|
|
|
|
// TODO Double-resolution printing in the x axis.
|
|
// ams |= AdvancedModeSettings::HIGH_RES_PRINTING;
|
|
|
|
printer.set_mode_settings(VariousModeSettings::AUTO_CUT, ams, 4)?;
|
|
|
|
// TODO this depends based on what tape is in use
|
|
// 128 lines (printer size)
|
|
// minus '84 dots' (1/width in manual 2.3.2)
|
|
// plus '7 dots' (5/width offset in manual 2.3.2).
|
|
// then halved......?
|
|
// let yoff = (128 - 84 + 7) >> 1;
|
|
|
|
// maybe you just center the printing?
|
|
let yoff = (128 - image.height()) >> 1;
|
|
|
|
for x in 0..lines {
|
|
let mut line = [0u8; 16];
|
|
|
|
for y in 0..(128 - yoff) {
|
|
let pix = y < image.height() && (image.get_pixel(x, y).0 == [0, 0, 0, 255]);
|
|
if pix {
|
|
let real_y = y + yoff;
|
|
line[(real_y >> 3) as usize] |= 128 >> (real_y & 0b0000_0111);
|
|
}
|
|
}
|
|
|
|
printer
|
|
.raster_line(line)
|
|
.with_context(|| format!("line {line:?}"))?;
|
|
}
|
|
|
|
printer.finish_printing(page == images.len() - 1)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|