Closed4
raqoteの生成画像をaxumでレスポンスとして返そうとしたかったやつ
問題はあるがとりあえず出来たは出来た・・・
use hyper::{Response, StatusCode};
use axum::prelude::*;
use image::png::PngEncoder;
use raqote::{LineCap,LineJoin,PathBuilder,Point,SolidSource,Source,Spread, StrokeStyle,Color, DrawOptions,DrawTarget, Gradient, GradientStop};
use std::net::SocketAddr;
fn img_sample() -> DrawTarget {
let mut dt = DrawTarget::new(400, 400);
let mut pb = PathBuilder::new();
pb.move_to(100., 10.);
pb.cubic_to(150., 40., 175., 0., 200., 10.);
pb.quad_to(120., 100., 80., 200.);
pb.quad_to(150., 180., 300., 300.);
pb.close();
let path = pb.finish();
let gradient = Source::new_radial_gradient(
Gradient {
stops: vec![
GradientStop {
position: 0.2,
color: Color::new(0xff, 0, 0xff, 0),
},
GradientStop {
position: 0.8,
color: Color::new(0xff, 0xff, 0xff, 0xff),
},
GradientStop {
position: 1.,
color: Color::new(0xff, 0xff, 0, 0xff),
},
],
},
Point::new(150., 150.),
128.,
Spread::Pad,
);
dt.fill(&path, &gradient, &DrawOptions::new());
let mut pb = PathBuilder::new();
pb.move_to(100., 100.);
pb.line_to(300., 300.);
pb.line_to(200., 300.);
let path = pb.finish();
dt.stroke(
&path,
&Source::Solid(SolidSource {
g: 0x0,
r: 0x0,
b: 0x80,
a: 0x80,
}),
&StrokeStyle {
cap: LineCap::Round,
join: LineJoin::Round,
width: 10.,
miter_limit: 2.,
dash_array: vec![10., 18.],
dash_offset: 16.,
},
&DrawOptions::new(),
);
dt
}
fn build_img() -> Vec<u8> {
let dt: DrawTarget = img_sample();
let d = dt.get_data_u8();
let mut buffer = Vec::new();
let _ = PngEncoder::new(&mut buffer).encode(d, 400, 400, image::ColorType::Rgba8);
buffer
}
#[tokio::main]
async fn main() {
let app = route("/img", get(img_handler));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
hyper::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
async fn img_handler() -> Response<Body> {
let img_buf = build_img();
return Response::builder()
.extension("png")
.status(StatusCode::OK)
.body(Body::from(img_buf))
.unwrap();
}
問題点
- 本来青いはずの点線が赤くなる
- raqoteには画像ファイルに保存する
write_png
という関数しか用意されておらず、バイナリの状態にするのが面倒そうだった - そこでPngEncoderを使ったが、もしかするとrとbが逆なのかも?
- しかしそれにしたってグラデーションは一緒なので、完全にそういう感じとも言えない・・・?
- 流石に自前バージョン用意するのもめんどくさくてやめた
axumの前に、warp、actix-webでも試していたので、そこらへんとの比較
- 基本的には好感触
- warpは画像で返すのがえらい面倒そうで挫折した
- actix-webはたしかに噂通り(他に比べると)重厚目だった
- axumは一番簡素に実装できた印象がある。
- ドキュメントがある程度網羅的でわかりやすかった印象
参考:actixこんな感じだった
async fn img_handler() -> impl Responder {
let im = img();
HttpResponse::Ok()
.encoding(ContentEncoding::Identity)
.set(ContentType::png())
.body(im)
}
このスクラップは2021/08/04にクローズされました