JavaScriptで生成した画像配列をHTMLのimgタグで表示する

JavaScriptで生成した画像配列をHTMLのimgタグで表示してみます。

これが全コードです。

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Dispaly image array using HTML img tag</title>  
  </head>
  <body>
    <script>
      // 画像の幅、高さ
      const width = 256;
      const height = 256;

      // 一次元配列に各ピクセルのRGBA値を格納する
      const array = new Array(width * height * 4); // 4 = RGBA
      for (let y = 0; y < height; ++y) {
        for (let x = 0; x < width; ++x) {
          const index = (x + (y * width)) * 4;
          array[index] = x; // Red
          array[index + 1] = y; // Green
          array[index + 2] = 0; // Blue
          array[index + 3] = 255; // Alpha
        }
      }

      // 配列をImageDataに変換する
      const image = new ImageData(new Uint8ClampedArray(array), width, height);

      // canvasにImageDataを描画する
      const canvas = document.createElement('canvas');
      canvas.width = width;
      canvas.height = height;
      const context = canvas.getContext('2d');
      context.putImageData(image, 0, 0);
      // document.body.appendChild(canvas); // 確認用

      // canvasからBlobを作成する
      canvas.toBlob((blob) => {
        // BlobのURLを作成してimgタグのsrc属性に設定する
        const img = document.createElement('img');
        img.src = URL.createObjectURL(blob);
        document.body.appendChild(img);
      }, 'image/png');
    </script>
  </body>
</html>
```

このHTMLで以下のような画像が表示されます。
![array-to-img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61569/7258cad3-c121-1e33-21e6-c00106b65251.png)


ステップごとに解説します。

まず、画像配列を作成します。ここでは、横方向に赤色に、縦方向に緑色になるようにしています。RGBAの各値を8bitで表現するので、最小値が0、最大値が255になります。

```js
// 一次元配列に各ピクセルのRGBA値を格納する
const array = new Array(width * height * 4); // 4 = RGBA
for (let y = 0; y < height; ++y) {
  for (let x = 0; x < width; ++x) {
    const index = (x + (y * width)) * 4;
    array[index] = x; // Red
    array[index + 1] = y; // Green
    array[index + 2] = 0; // Blue
    array[index + 3] = 255; // Alpha
  }
}
```

canvasに描画するために、[ImageData](https://developer.mozilla.org/ja/docs/Web/API/ImageData)に変換します。先ほどの配列を[Uint8ClampedArray](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray)に変換して引数として渡します。

```js
// 配列をImageDataに変換する
const image = new ImageData(new Uint8ClampedArray(array), width, height);
```

canvas要素を作成して、先ほど生成したImageDataを[putImageData](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/putImageData)を用いて描画します。

```js
// canvasにImageDataを描画する
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const context = canvas.getContext('2d');
context.putImageData(image, 0, 0);
// document.body.appendChild(canvas); // 確認用
```

canvasの描画結果を[toBlob](https://developer.mozilla.org/ja/docs/Web/API/HTMLCanvasElement/toBlob)を用いてBlobに変換します。img要素を作成して、そのsrc属性に[URL.createObjectURL](https://developer.mozilla.org/ja/docs/Web/API/URL/createObjectURL)で作成したURLを設定します。

```js
// canvasからBlobを作成する
canvas.toBlob((blob) => {
  // BlobのURLを作成してimgタグのsrc属性に設定する
  const img = document.createElement('img');
  img.src = URL.createObjectURL(blob);
  document.body.appendChild(img);
}, 'image/png');
```

以下、参考した記事です。

- [javascript \- Draw an exisiting ArrayBuffer into a Canvas without copying \- Stack Overflow](https://stackoverflow.com/questions/42410080/draw-an-exisiting-arraybuffer-into-a-canvas-without-copying)
- [JAVASCRIPT.INFO: Blob](https://ja.javascript.info/blob)