diff --git a/showbits-thermal-printer/src/documents/image/data.json b/showbits-thermal-printer/src/documents/image/data.json index 90528be..62b6f32 100644 --- a/showbits-thermal-printer/src/documents/image/data.json +++ b/showbits-thermal-printer/src/documents/image/data.json @@ -1,4 +1,6 @@ { + "title": "Moon", + "caption": "(on the moon)", "algo": "stucki", "bright": false, "seamless": false, diff --git a/showbits-thermal-printer/src/documents/image/main.typ b/showbits-thermal-printer/src/documents/image/main.typ index bee4a55..ebeec2d 100644 --- a/showbits-thermal-printer/src/documents/image/main.typ +++ b/showbits-thermal-printer/src/documents/image/main.typ @@ -3,17 +3,25 @@ #let data = json("data.json") -#let dithered = lib.dither( +#show: it => if data.seamless { + set page(margin: 0pt) + it +} else { it } + +#if data.title != none { + align(center, text(size: 32pt, data.title)) +} + +#lib.dither( read("image.png", encoding: none), bright: data.bright, algorithm: data.algo, ) -#if data.seamless { - set page(margin: 0pt) - dithered - if data.feed { lib.feed } -} else { - dithered - if data.feed { lib.feed } +#if data.caption != none { + align(center, text(size: 32pt, data.caption)) +} + +#if data.feed { + lib.feed } diff --git a/showbits-thermal-printer/src/documents/image/mod.rs b/showbits-thermal-printer/src/documents/image/mod.rs index bcd9ab6..3dcca83 100644 --- a/showbits-thermal-printer/src/documents/image/mod.rs +++ b/showbits-thermal-printer/src/documents/image/mod.rs @@ -16,6 +16,8 @@ use crate::{ #[derive(Serialize)] struct Data { + title: Option, + caption: Option, algo: String, bright: bool, seamless: bool, @@ -25,6 +27,8 @@ struct Data { pub async fn post(server: State, mut multipart: Multipart) -> somehow::Result { let mut image = None; let mut data = Data { + title: None, + caption: None, algo: "stucki".to_string(), bright: true, seamless: false, @@ -38,6 +42,12 @@ pub async fn post(server: State, mut multipart: Multipart) -> somehow::R let decoded = image::load_from_memory(&data)?.into_rgba8(); image = Some(decoded); } + Some("title") => { + data.title = Some(field.text().await?); + } + Some("caption") => { + data.caption = Some(field.text().await?); + } Some("algo") => { data.algo = field.text().await?; } diff --git a/showbits-thermal-printer/src/drawer.rs b/showbits-thermal-printer/src/drawer.rs index 9cbce78..7e92d89 100644 --- a/showbits-thermal-printer/src/drawer.rs +++ b/showbits-thermal-printer/src/drawer.rs @@ -1,7 +1,6 @@ mod backlog; mod chat_message; mod new_typst; -mod photo; mod tictactoe; use showbits_common::widgets::{FontStuff, HasFontStuff}; @@ -11,7 +10,7 @@ use crate::persistent_printer::PersistentPrinter; pub use self::{ backlog::BacklogDrawing, chat_message::ChatMessageDrawing, new_typst::NewTypstDrawing, - photo::PhotoDrawing, tictactoe::TicTacToeDrawing, + tictactoe::TicTacToeDrawing, }; pub const FEED: f32 = 96.0; diff --git a/showbits-thermal-printer/src/drawer/photo.rs b/showbits-thermal-printer/src/drawer/photo.rs deleted file mode 100644 index 981a029..0000000 --- a/showbits-thermal-printer/src/drawer/photo.rs +++ /dev/null @@ -1,60 +0,0 @@ -use image::{Luma, Pixel, RgbaImage}; -use showbits_common::{ - Node, Tree, WidgetExt, - color::{BLACK, WHITE}, - widgets::{Image, Text}, -}; -use taffy::{ - AlignItems, Display, FlexDirection, - style_helpers::{length, percent}, -}; - -use crate::persistent_printer::PersistentPrinter; - -use super::{Context, Drawing, FEED}; - -pub struct PhotoDrawing { - pub image: RgbaImage, - pub title: String, -} - -impl Drawing for PhotoDrawing { - fn draw(&self, printer: &mut PersistentPrinter, ctx: &mut Context) -> anyhow::Result<()> { - let mut tree = Tree::::new(WHITE); - - let mut image = self.image.clone(); - for pixel in image.pixels_mut() { - let [l] = pixel.to_luma().0; - let l = l as f32 / 255.0; // Convert to [0, 1] - let l = 1.0 - (0.4 * (1.0 - l)); // Lerp to [0.6, 1] - let l = (l.clamp(0.0, 1.0) * 255.0) as u8; // Convert back to [0, 255] - *pixel = Luma([l]).to_rgba(); - } - - let image = Image::new(image) - .with_dither_palette(&[BLACK, WHITE]) - .node() - .register(&mut tree)?; - - let title = Text::new() - .with_metrics(Text::default_metrics().scale(2.0)) - .and_plain(&self.title) - .widget(&mut ctx.font_stuff) - .node() - .register(&mut tree)?; - - let root = Node::empty() - .with_size_width(percent(1.0)) - .with_padding_bottom(length(FEED)) - .with_display(Display::Flex) - .with_flex_direction(FlexDirection::Column) - .with_align_items(Some(AlignItems::Center)) - .with_gap(length(8.0)) - .and_child(image) - .and_child(title) - .register(&mut tree)?; - - printer.print_tree(&mut tree, ctx, root)?; - Ok(()) - } -} diff --git a/showbits-thermal-printer/src/server.rs b/showbits-thermal-printer/src/server.rs index 9f301c2..b2b7dda 100644 --- a/showbits-thermal-printer/src/server.rs +++ b/showbits-thermal-printer/src/server.rs @@ -4,9 +4,7 @@ pub mod statuscode; use axum::{ Form, Router, - extract::{DefaultBodyLimit, Multipart, State}, - http::StatusCode, - response::{IntoResponse, Redirect, Response}, + extract::{DefaultBodyLimit, State}, routing::{get, post}, }; use serde::Deserialize; @@ -14,10 +12,10 @@ use tokio::{net::TcpListener, sync::mpsc}; use crate::{ documents, - drawer::{ChatMessageDrawing, Command, PhotoDrawing, TicTacToeDrawing}, + drawer::{ChatMessageDrawing, Command, TicTacToeDrawing}, }; -use self::{r#static::get_static_file, statuscode::status_code}; +use self::r#static::get_static_file; #[derive(Clone)] pub struct Server { @@ -40,7 +38,6 @@ pub async fn run(tx: mpsc::Sender, addr: String) -> anyhow::Result<()> "/image", post(documents::image::post).fallback(get_static_file), ) - .route("/photo", post(post_photo).fallback(get_static_file)) .route( "/text", post(documents::text::post).fallback(get_static_file), @@ -73,41 +70,6 @@ async fn post_chat_message(server: State, request: Form, mut multipart: Multipart) -> somehow::Result { - let mut image = None; - let mut title = None; - - while let Some(field) = multipart.next_field().await? { - match field.name() { - Some("image") => { - let data = field.bytes().await?; - let decoded = image::load_from_memory(&data)?.into_rgba8(); - image = Some(decoded); - } - Some("title") => { - title = Some(field.text().await?); - } - _ => {} - } - } - - let Some(image) = image else { - return Ok(status_code(StatusCode::UNPROCESSABLE_ENTITY)); - }; - - let Some(title) = title else { - return Ok(status_code(StatusCode::UNPROCESSABLE_ENTITY)); - }; - - let _ = server - .tx - .send(Command::draw(PhotoDrawing { image, title })) - .await; - Ok(Redirect::to("photo").into_response()) -} - // /tictactoe async fn post_tictactoe(server: State) { diff --git a/showbits-thermal-printer/static/photo.html b/showbits-thermal-printer/static/photo.html index 1e29d03..f23c445 100644 --- a/showbits-thermal-printer/static/photo.html +++ b/showbits-thermal-printer/static/photo.html @@ -137,9 +137,9 @@ canvas.toBlob((blob) => { const form = new FormData(); form.append("image", blob); - form.append("title", new Date().toLocaleString()); + form.append("caption", new Date().toLocaleString()); - fetch("photo", { method: "POST", body: form }).catch((error) => { + fetch("image", { method: "POST", body: form }).catch((error) => { console.error("Error uploading image:", error); }); });