2b8da321cded66a1c496555a7574560b005a2bd4
[litoprism.git] / src / main.rs
1 use std::io::Cursor;
2 use std::fmt::Display;
3 use std::fmt;
4 use actix_web::{get, web, App, HttpServer, HttpResponse, Responder, ResponseError, Result};
5 use actix_web::body::BoxBody;
6 use actix_web::http::StatusCode;
7 use image::{ImageBuffer, ColorType, Rgb, RgbImage, write_buffer_with_format};
8 use image::ImageOutputFormat::Png;
9
10 #[derive(Debug)]
11 struct ImageError(image::ImageError);
12
13 impl Display for ImageError {
14 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15 write!(f, "{}", &self.0)
16 }
17 }
18
19 impl ResponseError for ImageError {
20 fn status_code(&self) -> StatusCode {
21 StatusCode::INTERNAL_SERVER_ERROR
22 }
23
24 fn error_response(&self) -> HttpResponse<BoxBody> {
25 HttpResponse::InternalServerError().finish()
26 }
27 }
28
29 struct StringToRgb<'a> {
30 text: &'a str,
31 iter: Box<dyn Iterator<Item = char> + 'a>
32 }
33
34 impl<'a> StringToRgb<'a> {
35 fn new(text: &'a str) -> StringToRgb {
36 StringToRgb { text, iter: Box::new(text.chars()) }
37 }
38 }
39
40
41
42 impl Iterator for StringToRgb<'_> {
43 type Item = Rgb<u8>;
44 fn next(&mut self) -> Option<Rgb<u8>> {
45 let r = self.iter.next();
46 let g = self.iter.next();
47 let b = self.iter.next();
48 if r.is_none() && g.is_none() && b.is_none() {
49 None
50 }
51 else {
52 Some(Rgb([r.unwrap_or('\0') as u8, g.unwrap_or('\0') as u8, b.unwrap_or('\0') as u8]))
53 }
54 }
55 }
56
57 fn to_imageresult<T> (result: Result<T, image::ImageError>) -> Result<T, ImageError> {
58 match result {
59 Ok(v) => Ok(v),
60 Err(e) => Err(ImageError(e))
61 }
62 }
63
64 #[get("/hello/{name}")]
65 async fn greet(name: web::Path<String>) -> impl Responder {
66 format!("Hello {name}!")
67 }
68
69 #[get("/gen/{data}")]
70 async fn img_gen(data: web::Path<String>) -> Result<impl Responder> {
71 let mut cursor = Cursor::new(Vec::new());
72 let mut img: RgbImage = ImageBuffer::new(128, 128);
73 let mut pixels = img.pixels_mut();
74 //let mut rgb = Box::new(StringToRgb::new(&data));
75 let mut rgb = StringToRgb::new(&data);
76
77 for sp in rgb {
78 let mut dp = pixels.next().unwrap();
79 dp.0 = sp.0;
80 }
81
82 to_imageresult(write_buffer_with_format(&mut cursor, &img, 128, 128, ColorType::Rgb8, Png))?;
83 Ok(HttpResponse::build(StatusCode::OK)
84 .content_type("image/png")
85 .body(cursor.into_inner()))
86 }
87
88 #[actix_web::main] // or #[tokio::main]
89 async fn main() -> std::io::Result<()> {
90 HttpServer::new(|| {
91 App::new().service(greet).service(img_gen)
92 })
93 .bind(("127.0.0.1", 8080))?
94 .run()
95 .await
96 }