1. ホーム
  2. Web制作
  3. html5

ピクセル画像を描画するCanvasのサンプルコード

2022-01-21 17:20:22

プリアンブル

紅白歌合戦で遊んだ子供時代。特にあの頃の国産ジークが記憶に残っている。
マリオの奴思い出した。

子供の頃からドット絵のゲームが特に好きだったこともあり、ドット絵のスタイル自体は極めてシンプルな要素で構成された極めて複雑な絵なので、創作の余地が無限にあり、結果として忘れられない独特の画風になるのだと思います。そこで、大量生産用にピクセル・ドット・マトリックスで画像を生成するために、わかりやすい絵を借用したいと考えたのです。
初めて書いた短い記事なので、いろいろと至らない点があることをご容赦ください。

はじめに

クリア画像をピクセル調の画像に変換する方法とは?

まず理解しておかなければならないのは、ピクセルスタイルは単純な1色のブロックで構成されているということです。

そこで、まず画像をアップロードして、それを描画します。次に、画像を解析して色の値を取得し、各ピクセルの位置を決定します。そして、色値をキャンバスの対応する位置に再描画します。これが、ピクセルウィンドを簡単に実装する方法です。

実装方法

1. 元画像をアップロードする

<input type="file" accept=".jpeg,.jpg,.png" />
<script>
document.querySelector("input[type=file]").addEventListener("change",uploadImage, false);
</script>


まず、ファイルをアップロードするための入力をページに配置し、accept属性を使ってアップロードの種類を制限する必要があります。ここでは、jpeg、jpg、pngといった通常の画像のアップロードが含まれるためです。

また、変換が必要なファイルを取得するために、変更をリッスンします。

次にuploadImage関数を定義してみます。

function uploadImage(e) {
    let file = e.target.files[0];
    if (!file) return;
    let fileReader = new FileReader();
    fileReader.readAsDataURL(file);
    fileReader.onload = () => {
        createImage(fileReader);
        e.target.value = "";
        document.querySelectorAll("canvas").forEach(node=>{node.remove();})
    };
}

function createImage(obj) {
    let img = new Image();
    img.onload = () => {
        drawImage(img);
    };
    img.src = obj.result;
}

ここでは、アップロードされた画像のアドレスを fileReader.result で取得し、createImage 関数を書いて、Image としてインスタンス化されたファイルオブジェクトを受け取って canvas に描画しています。結局のところ、1つの関数で1つのことしかできないようにするのが良い習慣なのです。

2. 元画像を描画する

function drawImage(img) {
        let canvas = document.createElement("canvas");
        let ctx = canvas.getContext("2d");
        canvas.width = ctx.width;
        canvas.height = ctx.height
        let w = img.width,
          h = img.height;
        ctx.drawImage(img,0,0,w,h);
        document.body.appendChild(canvas);
 }

まず、画像をキャンバスに描画することを同時に実装してみましょう。具体的にはどのようなものでしょうか。今度は、どれくらいの大きさのピクセル画を生成したいかを考えます。ここでは、グローバル変数を作りたい、と思っています。

let width = 32;
let height = 32;
let size = 10;


生成する幅、高さ、ピクセルサイズを定義しています。widthとheightはその名の通り、幅が何ピクセルで高さが何ドットのものを生成したいかを示している。sizeはピクセルがどのくらいの大きさで塗りつぶされるかを示しており、サイズピクセルごとに色の値が取られている。
次に、drawImage関数を変形してみましょう。

function drawImage(img) {
    let canvas = document.createElement("canvas");
    let ctx = canvas.getContext("2d");
    canvas.width = ctx.width = width * size;
    canvas.height = ctx.height = height * size;
    let w = img.width,
        h = img.height;
    let v = w / h;
    if (v > 1) {
        w = width;
        h = w / v;
    } else {
        h = height;
        w = h * v;
    }
    ctx.drawImage(
        img,
        ((width - w) / 2) * size,
        ((height - h) / 2) * size,
        w * size,
        h * size
    );
    document.body.appendChild(canvas);
    
    let pxMap = createPxMap(ctx);
    drawPXCanvas(pxMap)
}

画像を描画し、ピクセル情報を含む配列のセットを生成して返すことを想定し、ピクセル風の生成を行います。
もちろん、2つの画像を比較するために、元の画像の幅と高さもピクセル画像で水平にし、キャンバスの中央に配置しました。

3. ピクセルアートの描画

function createPxMap(ctx){
    let pxMap = [];
    for (let i = 0; i < width * size; i += size) {
        for (let j = 0; j < height * size; j += size) {
            let pixel = ctx.getImageData(i, j, 1, 1).data;
            let color = `rgba(${pixel[0]},${pixel[1]},${pixel[2]},${pixel[3]/255})`;
            pxMap.push({ x: i / size, y: j / size, color });
        }
    }
    return pxMap;
}

まず、点の位置と色の情報を取得したいと思います。 ctx.getImageDataは、それぞれ赤、緑、青、透明度の情報を表すビット0〜3のバッファの配列を取得します。この情報を格納したい。
最後はいよいよピクセルの絵が描けるようになるのです。

function drawPXCanvas(pxMap) {
    let canvas = document.createElement("canvas");
    let ctx = canvas.getContext("2d");
    canvas.width = ctx.width = width * size;
    canvas.height = ctx.height = height * size;
    pxMap.forEach((px) => {
        const { color, x, y } = px;
        ctx.fillStyle = color;
        ctx.fillRect(x*size, y*size, size, size);
    });
    document.body.appendChild(canvas);
}


キャンバスを再生成して、先ほど収集したピクセル情報を一つずつキャンバスに描画していくので、簡単なピクセルペイントが出来上がります、簡単でしょう?

拡大する

実は、ピクセル情報を取得すると、canvas2dのピクセルペインティングを超えることができるんです。

また、次のような考え方もあります。

cssのbox-shadowを使ってピクセルアートを生成し、using: rootやscssを使ってサイズや位置を簡単に制御し、animationを使ってアニメーションを生成することができます。

webglを拡張して、3Dピクセルや他のスタイルを生成することもできます。

3d ピカチュウ

そして、ピクセル化された構図をフレーム単位でドリルダウンして解析し、動画やアニメーションを生成することができるのです。

Canvasでピクセル画像を描画するサンプルコードの紹介は以上となります。Canvas のピクセル化コンテンツに関する詳細については、スクリプトハウスの過去記事を検索するか、以下の関連記事を引き続きご覧ください。