はじめに
過去記事でRustとWebAssembly使ってAsciiアート生成ツールに挑戦した際に
ドット絵生成ツールにも挑戦したいと思ったので、
今回は、RustとWebAssembly使ってドット絵生成ツール的なのを作成しようと思います。
プロジェクトの作成
wasm-packのテンプレートから作成。
今回は、wasmでimageのdataを受け取り、ドット絵調に画像加工して出力する関数を作成する。
出力ベース画像は縦横比 512px x 512px とし、
押下されたButtonの内容と同じドット絵の比率に合わせたセル数に加工してみる。
// 省略
// セルのサイズ
let dot_size:u32 = input_size.parse().unwrap_or(8);
let cell_size:u32 = 512/dot_size;
let mut output_img = ImageBuffer::new(img.width(), img.height());
// セルごとに処理
for y in 0..img.height() / cell_size {
for x in 0..img.width() / cell_size {
// セルを切り出す
let cell = img.sub_image(
x * cell_size,
y * cell_size,
cell_size,
cell_size,
);
// セルを解析
let recognized_rgba = analyze_cell(cell.to_image());
for b in 0..cell_size {
for a in 0..cell_size {
output_img.put_pixel(a+(x*cell_size) , b+(y*cell_size),recognized_rgba);
}
}
}
}
// 省略
セルの色の判定ロジックは切り出したセルで出現回数が最多の色を採用する。
(Gemini1.5proにHashMapの使い方覚えるついでに下記ロジックを教えてもらった。max_by_keyとか知らないメソッド多いので勉強になる。)
// 省略
fn analyze_cell(cell: ImageBuffer<Rgba<u8>, Vec<u8>>) -> Rgba<u8> {
let mut counts = HashMap::new();
// ピクセルごとにRGBAをキーとして出現回数をカウント
for pixel in cell.pixels() {
*counts.entry(pixel).or_insert(0) += 1;
}
let result_rgba = counts
.into_iter()
.max_by_key(|&(_, count)| count)
.map(|(rgba, _)| rgba).unwrap();
*result_rgba
}
// 省略
今回の成果物
デモURL
デモ画像
・元画像
4x4で生成
8x8で生成
16x16で生成
32x32で生成
64x64で生成
128x128で生成
ソース
まとめ
成果物の中だと、16x16と32x32がドット絵の懐かしい感じがして好きでした。🎮
あと、4x4と8x8は粗すぎて何が何だか状態でした、、、
Rustにまだ慣れておらず、メソッドがわからない際はGemini1.5proを利用したが、
AIに頼らなくてもいいようにコツコツとメソッドを覚えていきたい。💪
※間違い等ありましたら、ご指摘いただけると助かります。