CanvasRenderingContext2D: putImageData() メソッド

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.

Canvas 2D API の CanvasRenderingContext2D.putImageData() メソッドは、指定の ImageData オブジェクトのデータをキャンバスに描画します。更新対象の矩形が指定された場合は、その矩形内のピクセルのみが描画されます。このメソッドは、キャンバスの変換行列の影響を受けません。

メモ: getImageData() メソッドを用いて、キャンバスから画像データを取得できます。

記事キャンバスとピクセル操作に、putImageData() およびキャンバスの内容の一般的な操作に関するさらなる情報があります。

構文

js
putImageData(imageData, dx, dy)
putImageData(imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight)

引数

imageData

ピクセル値の配列を持った ImageData オブジェクトです。

dx

描画先キャンバスに画像データを配置する横位置 (x 座標) です。

dy

描画先キャンバスに画像データを配置する縦位置 (y 座標) です。

dirtyX 省略可

画像データを取り出し始める左上の角の横位置 (x 座標) です。デフォルト値は 0 です。

dirtyY 省略可

画像データを取り出し始める左上の角の縦位置 (y 座標) です。デフォルト値は 0 です。

dirtyWidth 省略可

描画する矩形の幅です。デフォルト値は画像データの幅です。

dirtyHeight 省略可

描画する矩形の高さです。デフォルト値は画像データの高さです。

返値

なし (undefined)

例外

NotSupportedError DOMException

引数のいずれかが無限のとき投げられます。

InvalidStateError DOMException

指定された ImageData オブジェクトのデータがデタッチされているとき投げられます。

putImageData を理解する

このアルゴリズムが中で何をやっているかを理解するために、CanvasRenderingContext2D.fillRect() を用いた実装を用意しました。

HTML

html
<canvas id="canvas"></canvas>

JavaScript

js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

function putImageData(
  ctx,
  imageData,
  dx,
  dy,
  dirtyX,
  dirtyY,
  dirtyWidth,
  dirtyHeight,
) {
  const data = imageData.data;
  const height = imageData.height;
  const width = imageData.width;
  dirtyX = dirtyX || 0;
  dirtyY = dirtyY || 0;
  dirtyWidth = dirtyWidth !== undefined ? dirtyWidth : width;
  dirtyHeight = dirtyHeight !== undefined ? dirtyHeight : height;
  const limitBottom = dirtyY + dirtyHeight;
  const limitRight = dirtyX + dirtyWidth;
  for (let y = dirtyY; y < limitBottom; y++) {
    for (let x = dirtyX; x < limitRight; x++) {
      const pos = y * width + x;
      ctx.fillStyle = `rgba(${data[pos * 4 + 0]}, ${data[pos * 4 + 1]}, ${
        data[pos * 4 + 2]
      }, ${data[pos * 4 + 3] / 255})`;
      ctx.fillRect(x + dx, y + dy, 1, 1);
    }
  }
}

// 内容をキャンバスに描画する
ctx.fillRect(0, 0, 100, 100);
// 描画内容から ImageData オブジェクトを生成する
const imagedata = ctx.getImageData(0, 0, 100, 100);
// putImageData の動作の説明用の putImageData 関数を用いる
putImageData(ctx, imagedata, 150, 0, 50, 50, 25, 25);

結果

ブラウザーの最適化によるデータの消失

警告: 乗算済みアルファカラー値との変換ではデータが劣化するため、putImageData() でピクセルを設定した直後でも、対応する getImageData() で異なる値として読み込まれる可能性があります。

JavaScript

js
const canvas = document.createElement("canvas");
canvas.width = 1;
canvas.height = 1;
const context = canvas.getContext("2d");
const imgData = context.getImageData(0, 0, canvas.width, canvas.height);
const pixels = imgData.data;
pixels[0 + 0] = 1;
pixels[0 + 1] = 127;
pixels[0 + 2] = 255;
pixels[0 + 3] = 1;
console.log("before:", pixels);
context.putImageData(imgData, 0, 0);
const imgData2 = context.getImageData(0, 0, canvas.width, canvas.height);
const pixels2 = imgData2.data;
console.log("after:", pixels2);

以下のような出力になるかもしれません。

before: Uint8ClampedArray(4) [ 1, 127, 255, 1 ]
after: Uint8ClampedArray(4) [ 255, 255, 255, 1 ]

仕様書

Specification
HTML Standard
# dom-context-2d-putimagedata-dev

ブラウザーの互換性

BCD tables only load in the browser

関連情報