createImageData, getImageData, putImageData メソッド
構文
- imagedata = context .
createImageData(sw, sh) -
CSS ピクセルで指定された寸法の
ImageDataオブジェクトを返します(その寸法は、そのオブジェクトからアクセスできる実際のデバイスのピクセルとは異なる数に対応付けられるかもしれません)。返されたオブジェクトにあるすべてのピクセルは、透明な黒となります。 - imagedata = context .
createImageData(imagedata) -
引数と同じ寸法となる
ImageDataオブジェクトを返します。返されるオブジェクトのすべてのピクセルは透明な黒となります。引数が null なら、
NOT_SUPPORTED_ERR例外を投げます。 - imagedata = context .
getImageData(sx, sy, sw, sh) -
canvas の指定の矩形に対するイメージを含んだ
ImageDataオブジェクトを返します。引数がひとつでも有限でないなら、
NOT_SUPPORTED_ERR例外を投げます。引数で指定した幅と高さのいずれかひとつでも 0 であれば、INDEX_SIZE_ERR例外を投げます。 - imagedata .
width - imagedata .
height -
ImageDataオブジェクトのデータの実際の寸法を返します。単位はデバイスのピクセルです。 - imagedata .
data -
RGBA の順番のデータを含んだ 1 次元配列を返します。それぞれの値は 0 ~ 255 の範囲となります。
- context .
putImageData(imagedata, dx, dy [, dirtyX, dirtyY, dirtyWidth, dirtyHeight ]) -
canvas に指定の
ImageDataオブジェクトのデータを描画します。dirty 矩形が与えられると、その矩形のピクセルだけが描画されます。globalAlphaとglobalCompositeOperation属性は、シャドー属性と同じように、このメソッドの呼び出しの目的においては、無視されます。canvas 上のピクセルは無差別に置き換えられ、コンポジション、アルファ・ブレンド、シャドーなどは対象になりません。第 1 引数が
ImageDataオブジェクトでなければ、TYPE_MISMATCH_ERR例外を投げます。他の引数のいずれかひとつでも有限でないなら、NOT_SUPPORTED_ERR例外を投げます。
仕様
createImageData() メソッドは、新たにブランクの ImageData オブジェクトを初期化するために使います。このメソッドに 2 つの引数 sw と sh を与えて呼び出すと、矩形を表す ImageData オブジェクトが返さなければいけません。その矩形は、CSS ピクセルの単位で、幅が sw の絶対等級と、そして、高さが sh の絶対等級と等しくなります。imagedata 引数をひとつだけ与えて呼び出すと、引数として与えた ImageData オブジェクトと同じ寸法の矩形を表す ImageData オブジェクトを返さなければいけません。ImageData オブジェクトは透明な黒で塗りつぶされたものでなければいけません。
getImageData(sx, sy, sw, sh) メソッドは、canvas の領域のピクセルデータを表す ImageData オブジェクトを返さなければいけません。その領域は、それぞれの 4 つの角が、canvas の座標空間の単位で、(sx, sy),
(sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh) となる矩形で表されます。canvas の領域外にあるピクセルは、透明な黒として返されなければいけません。ピクセルは、事前に掛け合わされていないアルファ値として返されなければいけません。
createImageData() や getImageData()を呼び出すときに、無限大や NaN といった引数をひとつでも与えたなら、もしくは、、createImageData()メソッドを呼び出すときに、ひとつしか引数を与えていないのに、その引数が null なら、NOT_SUPPORTED_ERR 例外を発生させなければいけません。sw または sh のいずれかひとつでも 0 なら、このメソッドは INDEX_SIZE_ERR 例外を発生させなければいけません。
ImageData オブジェクトは、その width 属性が w にセットされ、イメージデータの行ごとに物理的なデバイスのピクセルの数となるように、height 属性は h にセットされ、イメージデータの行の数となるように、data 属性は、イメージデータを保持している CanvasPixelArray オブジェクトに初期化された状態で、初期化されなければいけません。少なくとも 1 ピクセル分のイメージデータが返されなければいけません。
CanvasPixelArray オブジェクトは、順序添え字を使って、イメージデータの各ピクセルのカラー・コンポーネントにアクセスできます。そのデータは、左から右向き、そして上から下の行に向けて、表されなければいけません。左上から始まり、各ピクセルは、赤、緑、青、アルファのコンポーネントの順序で与えられます。この配列で表される各デバイス・ピクセルの各コンポーネントは、0 ~ 255 の範囲となり、コンポーネントはそれぞれ 8 ビットずつで表されます。コンポーネントには、左上のピクセルの赤コンポーネントを 0 として増えていくインデックス番号が割り当てられます。
そのため、CanvasPixelArray オブジェクトは h×w×4 個での整数で表されます。CanvasPixelArray オブジェクトの length 属性は、この数字を返さなければいけません。
オブジェクトのインデックス番号付きプロパティは、0 ~ h×w×4-1 の範囲の数字となります。
CanvasPixelArray オブジェクトが、インデックス番号付きプロパティ index を取得できるようインデックス化されるなら、その戻り値は、その配列の index 番目のコンポーネントの値とならなければいけません。
CanvasPixelArray オブジェクトが、値 value を持ったインデックス番号付きプロパティindex を変更できるようインデックス化されるなら、その配列の index 番目のコンポーネントの値が value となるようセットされなければいけません。
幅と高さ(w と h)は、前述のメソッドの sw と sh 引数と違うかもしれません。例えば、canvas が高解像度ビットマップによって戻される場合や、sw や sh 引数がマイナスの場合です。
putImageData(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight) メソッドは、canvas に ImageData 構造からのデータを書き戻します。
このメソッドに、無限大や NaN の引数をひとつでも与えると、このメソッドは NOT_SUPPORTED_ERR 例外を発生させなければいけません。
putImageData()メソッドの第 1 引数に null を与えたり ImageData オブジェクトでないものを与えると、このメソッドは TYPE_MISMATCH_ERR 例外を発生させなければいけません。
最後の 4 つの引数が省略されると、それらは、それぞれ、0, 0, imagedata 構造の width, imagedata 構造の height と見なされなければいけません。
例外を発生させることがない引数を使って putImageData() メソッドを呼び出すと、このメソッドは次の通りに動作しなければいけません:
-
dxdevice を、canvas 座標空間の dx 座標に対応する canvas のピクセルデータにあるデバイスのピクセルの x 座標とします。
dydevice を、canvas 座標空間の dy 座標に対応する canvas のピクセルデータにあるデバイスのピクセルの y 座標とします。
-
dirtyWidth がマイナスなら、dirtyX を、dirtyX+dirtyWidth とし、dirtyWidth を dirtyWidth の絶対値と同じにします。
dirtyHeight がマイナスなら、dirtyY を、dirtyY+dirtyHeight とし、 dirtyHeight を dirtyHeight の絶対値と同じにします。
-
dirtyX がマイナスなら、dirtyWidth を、dirtyWidth+dirtyX とし、dirtyX を 0 とします。
dirtyY がマイナスなら、dirtyHeight を、dirtyHeight+dirtyY とし、 dirtyY を 0 とします。
-
dirtyX+dirtyWidth が imagedata 引数の
width属性より大きければ、dirtyWidth を、そのwidth属性の値から、dirtyX の値を引いたものとします。dirtyY+dirtyHeight が imagedata 引数の
height属性より大きければ、dirtyHeight を、そのheight属性の値から、dirtyY の値を引いたものとします。 -
これらの変更の後、dirtyWidth もしくは dirtyHeight のいずれかが 0 以下なら、canvas に何も作用せずに、これらの手順を中止します。
-
そうでなければ、dirtyX ≤ x < dirtyX+dirtyWidth and dirtyY ≤ y < dirtyY+dirtyHeight となる整数値 x と y に対して、canvas のピクセルデータにある座標 (dxdevice+x, dydevice+y) となるピクセルに、imagedata 構造の中の座標 (x, y) となるピクセルの 4 つのチャネルをコピーします。
指定の座標がデバイスの座標空間に正確に対応付けできないときのピクセルの丸め処理は、この仕様では定義していません。ただし、次の点は除きます:
context.putImageData(context.getImageData(x, y, w, h), p, q);
p が x や x と w の和より小さく、q が y や y と h の和より小さければ、x, y, w, h にどんな値を与えても、これはレンダリングに目に見える変化は無いことになります。ただし、次の点は除きます:
context.createImageData(w, h); context.getImageData(0, 0, w, h);
これら 2 つのコールは、同じ寸法の ImageData オブジェクトを返さなければいけません。つまり、ユーザーエージェントは、これらのメソッドの引数を、デバイスのピクセルの境界に対応付けできるように、丸めるかもしれませんが、その場合、createImageData(), getImageData(), putImageData()による操作すべてに対して丸め処理を実行しなければいけません。
アルファ・カラーを掛け合わせた変換は不可逆の性質を持つため、putImageData() メソッドを使ってセットされたピクセルは、getImageData()では違う値が返されることになります。
現在のパス、変換マトリックス、シャドー属性、グローバル・アルファ、クリッピング領域、グローバル・コンポジション演算子は、getImageData() と putImageData()メソッドに影響を与えてはいけません。
getImageData()によって返されるデータは、canvas に蓄積された状態の解像度になります。それは、利用されているディスプレイが高解像度ディスプレイの場合、各 CSS ピクセルに対してひとつのデバイスのピクセルとなるわけではありません。
次の例では、スクリプトを使って、ImageData オブジェクトを生成して、それに描画できるようにしています。
// canvas は <canvas> 要素のリファレンスです。
var context = canvas.getContext('2d');
// 空のスレートを生成
var data = context.createImageData(canvas.width, canvas.height);
// プラズマを生成
FillPlasma(data, 'green'); // 緑のプラズマ
// プラズマにクラウドを追加
AddCloud(data, data.width/2, data.height/2); // 中央にクラウドを入れる
// canvas にプラズマ+クラウドを描画する
context.putImageData(data, 0, 0);
// メソッドをサポートする
function FillPlasma(data, color) { ... }
function AddCloud(data, x, y) { ... }
これは、エッジ検出フィルタを実装するために、getImageData() と putImageData() を利用した例です。
<!DOCTYPE HTML>
<html>
<head>
<title>エッジ検出デモ</title>
<script>
var image = new Image();
function init() {
image.onload = demo;
image.src = "image.jpeg";
}
function demo() {
var canvas = document.getElementsByTagName('canvas')[0];
var context = canvas.getContext('2d');
// canvas にイメージを描画
context.drawImage(image, 0, 0);
// 操作するイメージデータを取得
var input = context.getImageData(0, 0, canvas.width, canvas.height);
// データを入れる空のスレートを取得
var output = context.createImageData(canvas.width, canvas.height);
// 便宜上、いくつかの変数のエイリアスを用意する
// input.width と input.height は、canvas.width と canvas.height と
// 同じではないかもしれないため、
// ここでは、input.width と input.height を使う点に注意
// (特に高解像度ディスプレイで違いが出るだろう)
var w = input.width, h = input.height;
var inputData = input.data;
var outputData = output.data;
// エッジ検出
for (var y = 1; y < h-1; y += 1) {
for (var x = 1; x < w-1; x += 1) {
for (var c = 0; c < 3; c += 1) {
var i = (y*w + x)*4 + c;
outputData[i] = 127 + -inputData[i - w*4 - 4] - inputData[i - w*4] - inputData[i - w*4 + 4] +
-inputData[i - 4] + 8*inputData[i] - inputData[i + 4] +
-inputData[i + w*4 - 4] - inputData[i + w*4] - inputData[i + w*4 + 4];
}
outputData[(y*w + x)*4 + 3] = 255; // alpha
}
}
// 操作後にイメージデータを入れる
context.putImageData(output, 0, 0);
}
</script>
</head>
<body onload="init()">
<canvas></canvas>
</body>
</html>
原文:http://www.w3.org/TR/2010/WD-2dcontext-20100624/#pixel-manipulation
サンプル
getImageData() と putImageData() メソッドは、canvas に描かれた図形をビットマップのイメージデータとして抜き出し、それを canvas 上に張り付けるために使います。
このサンプルでは、まず canvas に図形を描き(左側の図)、その中心部分の矩形を getImageData() メソッドを使ってビットマップイメージとして抜き出します。そして、それをもう一つの canvas に張り付けます(右側の図)。
var canvas = document.getElementById('c1');
if ( ! canvas || ! canvas.getContext ) { return false; }
var ctx = canvas.getContext('2d');
/* 半透明度を指定 */
ctx.globalAlpha = 0.7;
/* 円 #1 */
ctx.beginPath();
ctx.fillStyle = 'rgb(192, 80, 77)'; // 赤
ctx.arc(70, 45, 35, 0, Math.PI*2, false);
ctx.fill();
/* 円 #2 */
ctx.beginPath();
ctx.fillStyle = 'rgb(155, 187, 89)'; // 緑
ctx.arc(45, 95, 35, 0, Math.PI*2, false);
ctx.fill();
/* 円 #3 */
ctx.beginPath();
ctx.fillStyle = 'rgb(128, 100, 162)'; // 紫
ctx.arc(95, 95, 35, 0, Math.PI*2, false);
ctx.fill();
/* canvasに描いた図形から中心部分のイメージを抜き出す */
var image = ctx.getImageData(45, 45, 50, 50);
/* 2つ目のcanvas左上に抜き出したイメージを貼り付ける */
var canvas2 = document.getElementById('c2');
var ctx2 = canvas2.getContext('2d');
ctx2.fillStyle = "black";
ctx2.fillRect(0, 0, 140, 140);
ctx2.putImageData(image, 10, 10);
[getImageData() / putImageData() メソッドの実際のサンプル]
では、もうひとつ、サンプルをご覧頂きましょう。仕様にエッジ検出のサンプルコードが掲載されていますが、これを実際に試してみます。
まず、もとの画像です。

次に、上記の画像を、仕様のエッジ検出のサンプルコードを使って変換して、それを Canvas 上に描いたものです。

これは、Safari 4 または、Chrome 3 でご覧ください。Firefox 3.5 でもエラーにはなりませんが、結果が異なっています。[エッジ検出の実際のサンプルを見る]
ブラウザ対応状況
| Firefox | Safari | Chrome | Opera | IE | ExplorerCanvas |
|---|---|---|---|---|---|
| 2 ○ | 2 × | 1 × | 9.2 × | 9 ○ | 0002 × |
| 3 ○ | 3 × | 2 ○ | 9.5 △ | 3 × | |
| 3.5 ○ | 4 ○ | 3 ○ | 10 △ | ||
| 3.6 ○ | 5 ○ | 6 ○ | 10.60 △ |
Opera には、まだ pubImageData() メソッドが実装されていません。