add palette selection; make image request extractor
This commit is contained in:
parent
c7e57f3d3b
commit
599fb09503
36
src/api.rs
36
src/api.rs
|
@ -1,11 +1,12 @@
|
|||
use crate::display::EInkPanel;
|
||||
use crate::imageproc::{DitherMethod, DitherPalette, EInkImage};
|
||||
use axum::extract::Multipart;
|
||||
use axum::async_trait;
|
||||
use axum::extract::{FromRequest, Multipart, State};
|
||||
use axum::http::{header, StatusCode};
|
||||
use axum::response::IntoResponse;
|
||||
use axum::{extract::State, response::Response, routing::post, Router};
|
||||
use axum::{response::Response, routing::post, Router};
|
||||
use image::{ImageReader, RgbImage};
|
||||
use std::io::{BufWriter, Cursor};
|
||||
use std::io::Cursor;
|
||||
use std::str;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
@ -98,8 +99,15 @@ struct ImageRequest {
|
|||
palette: DitherPalette,
|
||||
}
|
||||
|
||||
impl ImageRequest {
|
||||
async fn from_multipart(mut parts: Multipart) -> Result<Self, AppError> {
|
||||
#[async_trait]
|
||||
impl<S> FromRequest<S> for ImageRequest
|
||||
where
|
||||
S: Send + Sync,
|
||||
{
|
||||
type Rejection = AppError;
|
||||
|
||||
async fn from_request(req: axum::extract::Request, state: &S) -> Result<Self, Self::Rejection> {
|
||||
let mut parts = Multipart::from_request(req, state).await?;
|
||||
let mut img = None;
|
||||
let mut palette = None;
|
||||
let mut dither_method = None;
|
||||
|
@ -141,13 +149,12 @@ impl ImageRequest {
|
|||
#[instrument(skip(ctx))]
|
||||
async fn set_image(
|
||||
State(ctx): State<Context>,
|
||||
parts: Multipart,
|
||||
img_req: ImageRequest,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
let call = ImageRequest::from_multipart(parts).await?;
|
||||
let mut buf = EInkImage::new(call.palette.value().to_vec());
|
||||
let mut buf = EInkImage::new(img_req.palette.value().to_vec());
|
||||
{
|
||||
let mut dither = call.dither_method.get_ditherer();
|
||||
dither.dither(&call.image, &mut buf);
|
||||
let mut dither = img_req.dither_method.get_ditherer();
|
||||
dither.dither(&img_req.image, &mut buf);
|
||||
}
|
||||
let cmd = DisplaySetCommand { img: Box::new(buf) };
|
||||
ctx.display_channel
|
||||
|
@ -158,12 +165,11 @@ async fn set_image(
|
|||
|
||||
/// generates a dithered image based on the given image and the dithering parameters.
|
||||
/// Can be used to see how the dithering and palette choices affect the result.
|
||||
async fn preview_image(parts: Multipart) -> Result<impl IntoResponse, AppError> {
|
||||
let call = ImageRequest::from_multipart(parts).await?;
|
||||
let mut buf = EInkImage::new(call.palette.value().to_vec());
|
||||
async fn preview_image(img_req: ImageRequest) -> Result<impl IntoResponse, AppError> {
|
||||
let mut buf = EInkImage::new(img_req.palette.value().to_vec());
|
||||
{
|
||||
let mut dither = call.dither_method.get_ditherer();
|
||||
dither.dither(&call.image, &mut buf);
|
||||
let mut dither = img_req.dither_method.get_ditherer();
|
||||
dither.dither(&img_req.image, &mut buf);
|
||||
}
|
||||
// Convert buf into a png image.
|
||||
let img = buf.into_rgbimage();
|
||||
|
|
|
@ -21,12 +21,12 @@ const DISPLAY_PALETTE: [Srgb; 7] = [
|
|||
];
|
||||
|
||||
const SIMPLE_PALETTE: [Srgb; 7] = [
|
||||
Srgb::new(0.0,0.0,0.0), // Black
|
||||
Srgb::new(1.0,1.0,1.0), // White
|
||||
Srgb::new(0.0, 1.0, 0.0), // Green
|
||||
Srgb::new(0.0, 0.0, 1.0), // Blue
|
||||
Srgb::new(1.0, 0.0, 0.0), // Red
|
||||
Srgb::new(1.0, 1.0, 0.0), // Yellow
|
||||
Srgb::new(0.0, 0.0, 0.0), // Black
|
||||
Srgb::new(1.0, 1.0, 1.0), // White
|
||||
Srgb::new(0.0, 1.0, 0.0), // Green
|
||||
Srgb::new(0.0, 0.0, 1.0), // Blue
|
||||
Srgb::new(1.0, 0.0, 0.0), // Red
|
||||
Srgb::new(1.0, 1.0, 0.0), // Yellow
|
||||
Srgb::new(0.757, 0.443, 0.165), // Orange
|
||||
];
|
||||
|
||||
|
@ -37,10 +37,11 @@ pub enum DitherPalette {
|
|||
}
|
||||
|
||||
impl DitherPalette {
|
||||
pub fn value(&self) -> &[Srgb] {
|
||||
#[must_use]
|
||||
pub const fn value(&self) -> &[Srgb] {
|
||||
match self {
|
||||
Self::Default => &DISPLAY_PALETTE,
|
||||
Self::Simple => &DISPLAY_PALETTE, // FIXME: use simple pallete based on binary.
|
||||
Self::Simple => &SIMPLE_PALETTE, // FIXME: use simple pallete based on binary.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +95,10 @@ impl EInkImage {
|
|||
pub fn into_rgbimage(&self) -> RgbImage {
|
||||
RgbImage::from_fn(self.buf.width(), self.buf.height(), |x, y| {
|
||||
let idx = self.buf.get_pixel(x, y).0[0];
|
||||
let disp_color = self.palette.get(idx as usize).unwrap();
|
||||
let disp_color = self
|
||||
.palette
|
||||
.get(idx as usize)
|
||||
.expect("Palette will never be out of bounds");
|
||||
let arr: [u8; 3] = disp_color.into_format().into();
|
||||
imgRgb(arr)
|
||||
})
|
||||
|
@ -174,7 +178,7 @@ fn compute_error_adjusted_color(orig: &Lab, err: &Lab, weight: f32) -> Lab {
|
|||
/// ``DiffusionPoint`` is part of the diffusion matrix, represented by a shift in x and y and an error
|
||||
/// scaling factor.
|
||||
#[derive(Debug)]
|
||||
struct DiffusionPoint {
|
||||
pub struct DiffusionPoint {
|
||||
xshift: i32,
|
||||
yshift: i32,
|
||||
scale: f32,
|
||||
|
|
Loading…
Reference in a new issue