5
4

RustとWebAssemblyでドット絵フィルター作ってみた_修正版

Posted at

はじめに

下記で作ったドット絵フィルターを友人に見せたところ

友人「解像度低い映像になっただけやん。。。😑」

と言われたのでリベンジも含めて修正版を投稿します。

前回の成果物のフィルター

RustとWebAssemblyでドット絵フィルター作ってみた_002.jpg

プロジェクトの作成

前回作成したドット絵フィルターが微妙な理由は、

色合いがドット絵調ではなかったことがあげられる。😑

なので今回は、色をなるべくドット絵調に近づけてみる。

そもそもドット絵の色って何だろうと思い調べたところ、

下記のようなファミコンカラーパレット(ファミコン52色)と呼ばれる色があるみたいなので

これをベースに色を変更してみる

ファミコンカラーパレットについて

前回作成したもの加えて、

下記でcolorsのrgbが引数のrgbに一番近いものを返し、rgbを変換する。

lib.rs

// 省略

fn closest_color(r: u32, g: u32, b: u32) -> (u32, u32, u32) {
    let colors = [
        (171, 0, 19),  // 赤みがかった濃いピンク
        (231, 0, 91),  // 鮮やかなピンク
        (255, 119, 183),  // 薄いピンク
        (255, 199, 219),  // とても薄いピンク
        (167, 0, 0),  // 暗い赤
        (219, 43, 0),  // やや暗い赤
        (255, 119, 99),  // 明るい赤
        (255, 191, 179),  // 薄い赤
        (127, 11, 0),  // 暗いオレンジ
        (203, 79, 15),  // やや暗いオレンジ
        (255, 155, 59),  // 明るいオレンジ
        (255, 219, 171),  // 薄いオレンジ
        (67, 47, 0),  // 暗い黄色
        (139, 115, 0),  // やや暗い黄色
        (243, 191, 63),  // 明るい黄色
        (255, 231, 163),  // 薄い黄色
        (0, 71, 0),  // 暗い緑
        (0, 151, 0),  // やや暗い緑
        (131, 211, 19),  // 明るい緑
        (227, 255, 163),  // 薄い緑
        (0, 81, 0),  // 暗い青緑
        (0, 171, 0),  // やや暗い青緑
        (79, 223, 75),  // 明るい青緑
        (171, 243, 191),  // 薄い青緑
        (0, 63, 23),  // 暗いシアン
        (0, 147, 59),  // やや暗いシアン
        (88, 248, 152),  // 明るいシアン
        (179, 255, 207),  // 薄いシアン
        (27, 63, 95),  // 暗い青
        (0, 131, 139),  // やや暗い青
        (0, 235, 219),  // 明るい青
        (159, 255, 243),  // 薄い青
        (39, 27, 143),  // 暗い紫
        (0, 115, 239),  // やや暗い紫
        (63, 191, 255),  // 明るい紫
        (171, 231, 255),  // 薄い紫
        (0, 0, 171),  // 暗い藍色
        (35, 59, 239),  // やや暗い藍色
        (95, 115, 255),  // 明るい藍色
        (199, 215, 255),  // 薄い藍色
        (71, 0, 159),  // 暗いマゼンタ
        (131, 0, 243),  // やや暗いマゼンタ
        (167, 139, 253),  // 明るいマゼンタ
        (215, 203, 255),  // 薄いマゼンタ
        (143, 0, 119),  // 暗いピンク
        (191, 0, 191),  // やや暗いピンク
        (247, 123, 255),  // 明るいピンク
        (255, 199, 255),  // 薄いピンク
        (0, 0, 0),  // 黒
        (117, 117, 117),  // 灰色
        (188, 188, 188),  // 薄い灰色
        (255, 255, 255)  // 白
    ];
    *colors
        .iter()
        .min_by_key(|&&(cr, cg, cb)| color_distance(r, g, b, cr, cg, cb))
        .unwrap()
}

fn color_distance(r1: u32, g1: u32, b1: u32, r2: u32, g2: u32, b2: u32) -> u32 {
    let r_diff = r1 as i32 - r2 as i32;
    let g_diff = g1 as i32 - g2 as i32;
    let b_diff = b1 as i32 - b2 as i32;
    // 3次元空間上の距離を計算
    (r_diff * r_diff + g_diff * g_diff + b_diff * b_diff) as u32
}

// 省略

上記のフィルター結果は下記、

元画像(実際には映像)

RustとWebAssemblyでドット絵フィルター作ってみた_修正版_001.jpg

フィルター適用後

RustとWebAssemblyでドット絵フィルター作ってみた_修正版_002.jpg

うーん、スマホの水色がでてない、、、😑

あと、ドット絵調の割には、色が全体的に薄いかもしれない

なので、彩度を上げるフィルターもかけてみる

lib.rs

// 省略

  for i in 0..width * height {
        let index = i * 4; // RGBAなので4倍

        let r = buffer[index] as f32;
        let g = buffer[index + 1] as f32;
        let b = buffer[index + 2] as f32;

        // HSLは、色相(Hue)、彩度(Saturation)、明度(Lightness) の3つの要素で色を表現する色空間
        let (h, s, l) = rgb_to_hsl(r, g, b);

        let new_s = s * 2.0; // 2倍に設定
        let new_s = new_s.clamp(0.0, 1.0); // 彩度が1.0まで

        // RGBに変換
        let (new_r, new_g, new_b) = hsl_to_rgb(h, new_s, l);
        buffer[index] = new_r as u8;
        buffer[index + 1] = new_g as u8;
        buffer[index + 2] = new_b as u8;
    }

// 省略

元画像(実際には映像)

RustとWebAssemblyでドット絵フィルター作ってみた_修正版_001.jpg

フィルター適用後

RustとWebAssemblyでドット絵フィルター作ってみた_修正版_003.jpg

さっきよりは、色が出ていてドット絵調っぽい感じになった。

(まだまだ微妙なところもあるが、、)とりあえず完成!

今回の成果物

デモURL

ソース

まとめ

前回のドット絵フィルターを修正してみた。💪

まだまだ、ドット絵というには微妙な感じなので、、、😥

もう少し調査して近づけたら、また記事にしようと思う。🗒️

※間違い等ありましたら、ご指摘いただけると助かります。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4