c9c48b8338d13255985ec58eaba7af688ffb1f96
4 use std
::borrow
::BorrowMut
;
6 use num_traits
::cast
::AsPrimitive
;
7 use percent_encoding
::percent_decode_str
;
8 use actix_web
::{get
, web
, App
, HttpServer
, HttpRequest
, HttpResponse
, Responder
, ResponseError
, Result
};
9 use actix_web
::body
::BoxBody
;
10 use actix_web
::http
::StatusCode
;
11 use image
::{ImageBuffer
, ColorType
, Rgb
, RgbImage
, write_buffer_with_format
};
12 use image
::ImageOutputFormat
::Png
;
13 use image
::imageops
::{FilterType
, resize
};
14 use image
::error
::{LimitError
, LimitErrorKind
};
18 struct ImageError(image
::ImageError
);
20 impl Display
for ImageError
{
21 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
22 write
!(f
, "{}", &self.0)
26 impl ResponseError
for ImageError
{
27 fn status_code(&self) -> StatusCode
{
28 StatusCode
::INTERNAL_SERVER_ERROR
31 fn error_response(&self) -> HttpResponse
<BoxBody
> {
32 HttpResponse
::InternalServerError().body(format
!("{}\n", &self))
36 struct ToRgbIter
<'a
, T
> where T
: AsPrimitive
<u8> {
37 iter
: Box
<&'a
mut dyn Iterator
<Item
= T
>>
40 impl<'a
, T
: AsPrimitive
<u8>> ToRgbIter
<'a
, T
> {
41 fn new(data
: &'a
mut (dyn Iterator
<Item
= T
>)) -> ToRgbIter
<T
> {
42 ToRgbIter
{ iter
: Box
::new(data
) }
46 impl<T
: AsPrimitive
<u8> + Zero
> Iterator
for ToRgbIter
<'_
, T
> {
48 fn next(&mut self) -> Option
<Rgb
<u8>> {
49 if let Some(r
) = self.iter
.next() {
50 let g
= self.iter
.next().unwrap
_or
(T
::zero());
51 let b
= self.iter
.next().unwrap
_or
(T
::zero());
52 Some(Rgb([r
.as_(), g
.as_(), b
.as_()]))
60 fn to_imageresult
<T
> (result
: Result
<T
, image
::ImageError
>) -> Result
<T
, ImageError
> {
63 Err(e
) => Err(ImageError(e
))
67 #[get("/hello/{name}")]
68 async
fn greet(name
: web
::Path
<String
>, req
: HttpRequest
) -> impl Responder
{
69 println
!("{:?}", req
);
70 format
!("Hello {name}!")
73 fn make_png(dim_x
: u32, dim_y
: u32, scale
: u32, data
: &mut dyn Iterator
<Item
= u8>) -> Result
<Cursor
<Vec
<u8>>, ImageError
> {
74 let mut img
: RgbImage
= ImageBuffer
::new(dim_x
, dim_y
);
75 let mut pixels
= img
.pixels_mut();
77 for sp
in ToRgbIter
::new(data
) {
78 let mut dp
= pixels
.next().ok_or(ImageError(image
::ImageError
::Limits(LimitError
::from_kind(LimitErrorKind
::DimensionError
))))?
;
83 let tdim_x
= dim_x
* scale
;
84 let tdim_y
= dim_y
* scale
;
85 let img
= resize(&img
, tdim_x
, tdim_y
, FilterType
::Nearest
);
86 let mut cursor
= Cursor
::new(Vec
::new());
87 to_imageresult(write_buffer_with_format(&mut cursor
, &img
, tdim_x
, tdim_y
, ColorType
::Rgb8
, Png
))?
;
91 #[get("/gen/0/{data}")]
92 async
fn img_gen0(req
: HttpRequest
) -> Result
<impl Responder
> {
93 let data
= req
.ur
i().path().split("/").skip(3).next().unwrap
();
94 let cursor
= make_png(32, 32, 16, percent_decode_str(&data
).into
_iter
().borrow_mut())?
;
95 Ok(HttpResponse
::build(StatusCode
::OK
)
96 .content_type("image/png")
97 .body(cursor
.into
_inner
()))
100 #[get("/gen/1/{dim_x}/{dim_y}/{scale}/{data}")]
101 async
fn img_gen1(req
: HttpRequest
, path
: web
::Path
<(u32, u32, u32)>) -> Result
<impl Responder
> {
102 let (dim_x
, dim_y
, scale
) = path
.into
_inner
();
103 let data
= req
.ur
i().path().split("/").skip(6).next().unwrap
();
104 let cursor
= make_png(dim_x
, dim_y
, scale
, percent_decode_str(&data
).into
_iter
().borrow_mut())?
;
105 Ok(HttpResponse
::build(StatusCode
::OK
)
106 .content_type("image/png")
107 .body(cursor
.into
_inner
()))
110 #[actix_web::main] // or #[tokio::main]
111 async
fn main() -> std
::io
::Result
<()> {
118 .bind(("127.0.0.1", 8080))?