Remove /photo endpoint
This commit is contained in:
parent
2451bb3d76
commit
d32be913fd
7 changed files with 34 additions and 113 deletions
|
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
"title": "Moon",
|
||||
"caption": "(on the moon)",
|
||||
"algo": "stucki",
|
||||
"bright": false,
|
||||
"seamless": false,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ use crate::{
|
|||
|
||||
#[derive(Serialize)]
|
||||
struct Data {
|
||||
title: Option<String>,
|
||||
caption: Option<String>,
|
||||
algo: String,
|
||||
bright: bool,
|
||||
seamless: bool,
|
||||
|
|
@ -25,6 +27,8 @@ struct Data {
|
|||
pub async fn post(server: State<Server>, mut multipart: Multipart) -> somehow::Result<Response> {
|
||||
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<Server>, 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?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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::<Context>::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(())
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Command>, 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<Server>, request: Form<PostChatMessageF
|
|||
.await;
|
||||
}
|
||||
|
||||
// /photo
|
||||
|
||||
async fn post_photo(server: State<Server>, mut multipart: Multipart) -> somehow::Result<Response> {
|
||||
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<Server>) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue