Implement /pgen/0
authorMegaBrutal <code+git@megabrutal.com>
Thu, 14 Jul 2022 21:05:15 +0000 (23:05 +0200)
committerMegaBrutal <code+git@megabrutal.com>
Thu, 14 Jul 2022 21:05:15 +0000 (23:05 +0200)
src/main.rs

index ca0b17a4e70f9294ff2799f94a9ae52479b00c1b..7340b0bc02a8390955d5451b6e50f48c43495d67 100644 (file)
@@ -2,6 +2,7 @@ use std::io::Cursor;
 use std::fmt::Display;
 use std::fmt;
 use std::borrow::BorrowMut;
+use std::sync::{Arc, Mutex};
 use num_traits::Zero;
 use num_traits::cast::AsPrimitive;
 use percent_encoding::percent_decode_str;
@@ -70,27 +71,65 @@ fn to_imageresult<T> (result: Result<T, image::ImageError>) -> Result<T, ImageEr
     }
 }
 
+struct Canvas {
+    pen: usize,
+    img: RgbImage
+}
+
+impl Canvas {
+    fn new(width: u32, height: u32) -> Canvas {
+        Canvas { pen: 0, img: ImageBuffer::new(width, height) }
+    }
+
+    fn from_image(img: RgbImage) -> Canvas {
+        Canvas { pen: 0, img }
+    }
+
+    /*fn replace(&self, img: RgbImage, pen: usize) -> Canvas {
+        self.img = img;
+        self.pen = pen;
+        self
+    }*/
+
+    fn advance_pen(mut self, offset: usize) -> Canvas {
+        //Canvas { pen: self.pen + offset, img: self.img }
+        self.pen += offset;
+        self
+    }
+}
+
 #[get("/hello/{name}")]
 async fn greet(name: web::Path<String>, req: HttpRequest) -> impl Responder {
     println!("{:?}", req);
     format!("Hello {name}!")
 }
 
-fn make_png(dim_x: u32, dim_y: u32, scale: u32, data: &mut dyn Iterator<Item = u8>) -> Result<Cursor<Vec<u8>>, ImageError> {
-    // Image must not be larger than 1 megapixel
-    if dim_x * dim_y * scale > 1048576 {
-        return Err(ImageError::dimension_error())
-    }
-
-    let mut img: RgbImage = ImageBuffer::new(dim_x, dim_y);
-    let mut pixels = img.pixels_mut();
+fn rgb_encode_to_canvas(mut canvas: Canvas, data: &mut dyn Iterator<Item = u8>) -> Result<Canvas, ImageError> {
+    let mut pixels = canvas.img.pixels_mut().skip(canvas.pen);
+    let mut counter = 0;
 
     for sp in ToRgbIter::new(data) {
         let mut dp = pixels.next().ok_or(ImageError::dimension_error())?;
         println!("{:?}", sp);
         dp.0 = sp.0;
+        counter += 1;
     }
 
+    Ok(canvas.advance_pen(counter))
+}
+
+fn rgb_encode(img: RgbImage, data: &mut dyn Iterator<Item = u8>) -> Result<RgbImage, ImageError> {
+    Ok(rgb_encode_to_canvas(Canvas::from_image(img), data)?.img)
+}
+
+fn make_png(dim_x: u32, dim_y: u32, scale: u32, data: &mut dyn Iterator<Item = u8>) -> Result<Cursor<Vec<u8>>, ImageError> {
+    // Image must not be larger than 1 megapixel
+    if dim_x * dim_y * scale > 1048576 {
+        return Err(ImageError::dimension_error())
+    }
+
+    let mut img: RgbImage = rgb_encode(ImageBuffer::new(dim_x, dim_y), data)?;
+
     let tdim_x = dim_x * scale;
     let tdim_y = dim_y * scale;
     let img = resize(&img, tdim_x, tdim_y, FilterType::Nearest);
@@ -103,6 +142,7 @@ fn make_png(dim_x: u32, dim_y: u32, scale: u32, data: &mut dyn Iterator<Item = u
 async fn img_gen0(req: HttpRequest) -> Result<impl Responder> {
     let data = req.uri().path().split("/").skip(3).next().unwrap();
     let cursor = make_png(32, 32, 16, percent_decode_str(&data).into_iter().borrow_mut())?;
+    println!("{:?}", &cursor);
     Ok(HttpResponse::build(StatusCode::OK)
        .content_type("image/png")
        .body(cursor.into_inner()))
@@ -118,14 +158,35 @@ async fn img_gen1(req: HttpRequest, path: web::Path<(u32, u32, u32)>) -> Result<
        .body(cursor.into_inner()))
 }
 
+#[get("/pgen/0/{data}")]
+async fn img_pgen0(req: HttpRequest, canvas0: web::Data<Arc<Mutex<Option<Canvas>>>>) -> Result<impl Responder> {
+    let data = req.uri().path().split("/").skip(3).next().unwrap();
+    let mut cursor = Cursor::new(Vec::new());
+    let tdim_x = 32;
+    let tdim_y = 32;
+    {
+        let mut canvas_option = &mut *canvas0.lock().unwrap();
+        let canvas = canvas_option.take();
+        let canvas = rgb_encode_to_canvas(canvas.expect("Canvas doesn't exist!"), percent_decode_str(&data).into_iter().borrow_mut())?;
+        to_imageresult(write_buffer_with_format(&mut cursor, &canvas.img, tdim_x, tdim_y, ColorType::Rgb8, Png))?;
+        canvas_option.insert(canvas);
+    }
+    Ok(HttpResponse::build(StatusCode::OK)
+       .content_type("image/png")
+       .body(cursor.into_inner()))
+}
+
 #[actix_web::main] // or #[tokio::main]
 async fn main() -> std::io::Result<()> {
     env_logger::init();
-    HttpServer::new(|| {
+    let canvas0 = Arc::new(Mutex::new(Some(Canvas::new(32, 32))));
+    HttpServer::new(move || {
         App::new()
             .service(greet)
             .service(img_gen0)
             .service(img_gen1)
+            .service(img_pgen0)
+            .app_data(web::Data::new(canvas0.clone()))
     })
     .bind(("127.0.0.1", 8080))?
     .run()