JavaScript プログラミング講座

 

ImageData について

 


■ ImageData について

 
Canvas 2D Context 関連の機能です。
 
ImageData オブジェクトは、ビットマップ1枚分に相当します。
 
ピクセルカラーを、直接編集できます。
 


 

ImageData オブジェクトを作成する

 
 


■ImageData オブジェクトを作成する(サイズを指定)

 
createImageData() メソッドを使用します。
 
引数に、幅と高さを指定します。
 
すべてのピクセルは、透明黒色(0x00000000)で初期化されます。
 
CanvasRenderingContext2D.createImageData ( sw , sh ) :ImageData
第01引数 Number幅を指定。(単位:ピクセル値)
第02引数 Number高さを指定。(単位:ピクセル値)
戻り値 ImageData新しい ImageData オブジェクトが得られる。
 
■使用例
 
新しい ImageData オブジェクトを作成する(サイズを指定)

// ------------------------------------------------------------
// HTMLCanvasElement オブジェクトを作成する
// ------------------------------------------------------------
var canvas = document.createElement("canvas");

// BODY のノードリストに登録する
document.body.appendChild(canvas);

// ------------------------------------------------------------
// CanvasRenderingContext2D オブジェクトを取得する
// ------------------------------------------------------------
var context = canvas.getContext("2d");

// ------------------------------------------------------------
// 新しい ImageData オブジェクトを作成する
// ------------------------------------------------------------
var image_data = context.createImageData( 200 , 100 );

// 出力テスト
console.log(image_data);
 

■ImageData オブジェクトを作成する(サイズを継承)

 
createImageData() メソッドを使用します。
 
第01引数に、ソースとなる ImageData オブジェクトを指定します。
 
サイズ値が継承されます。
 
すべてのピクセルは、透明黒色(0x00000000)で初期化されます。
 
ImageData の複製ではありません。
 
CanvasRenderingContext2D.createImageData ( imagedata ) :ImageData
第01引数 Numberソースとなる ImageData オブジェクトを指定。(サイズ値が継承される)
戻り値 ImageData新しい ImageData オブジェクトが得られる。
 
■使用例
 
新しい ImageData オブジェクトを作成する(サイズを継承)

// ------------------------------------------------------------
// HTMLCanvasElement オブジェクトを作成する
// ------------------------------------------------------------
var canvas = document.createElement("canvas");

// BODY のノードリストに登録する
document.body.appendChild(canvas);

// ------------------------------------------------------------
// CanvasRenderingContext2D オブジェクトを取得する
// ------------------------------------------------------------
var context = canvas.getContext("2d");

// ------------------------------------------------------------
// 新しい ImageData オブジェクトを作成する(サイズを指定)
// ------------------------------------------------------------
var image_data0 = context.createImageData( 200 , 100 );

// ------------------------------------------------------------
// 新しい ImageData オブジェクトを作成する(サイズを継承)
// ------------------------------------------------------------
var image_data1 = context.createImageData( image_data0 );

// 出力テスト
console.log(image_data0);
console.log(image_data1);
 


 

ImageData の内部データについて

 
 


■ImageData の機能一覧

 
■プロパティ
 
プロパティ名説明
widthNumber幅(ピクセル数)を取得する
heightNumber高さ(ピクセル数)を取得する
dataUint8ClampedArrayピクセルカラーのバイナリ配列を取得する(編集可能)
 

■ピクセルカラーを編集する

 
data プロパティを使用します。
 
中身は、Uint8ClampedArray オブジェクトです。
 
型付き配列の一種です。
 
RGBAカラー(32bit) が、順番に格納されています。
 
(赤|緑|青|透過) | (赤|緑|青|透過) | (赤|緑|青|透過) ...
 
■ピクセルカラーを編集する関数
 
ピクセルカラーを編集する関数

// ------------------------------------------------------------
// RGBAカラー(32bit) を読み取る関数
// ------------------------------------------------------------
function ImageDataGetColorRGBA( imageData , x , y ){
	var a = imageData.data;
	var p = (y * imageData.width + x) * 4;
	return ((a[p + 0] << 24) | (a[p + 1] << 16) | (a[p + 2] << 8) | (a[p + 3] << 0)) >>> 0;
}

// ------------------------------------------------------------
// RGBAカラー(32bit) を書き込む関数
// ------------------------------------------------------------
function ImageDataSetColorRGBA( imageData , x , y , color_rgba ){
	var a = imageData.data;
	var p = (y * imageData.width + x) * 4;
	a[p + 0] = (color_rgba >>> 24) & 0xff;
	a[p + 1] = (color_rgba >>> 16) & 0xff;
	a[p + 2] = (color_rgba >>>  8) & 0xff;
	a[p + 3] = (color_rgba >>>  0) & 0xff;
}
 
■使用例
 
ImageData オブジェクトのピクセルカラーを編集する(TypedArray)

// ------------------------------------------------------------
// HTMLCanvasElement オブジェクトを作成する
// ------------------------------------------------------------
var canvas = document.createElement("canvas");

// キャンバスのサイズを設定する
canvas.width  = 256;
canvas.height = 256;

// BODY のノードリストに登録する
document.body.appendChild(canvas);

// ------------------------------------------------------------
// CanvasRenderingContext2D オブジェクトを取得する
// ------------------------------------------------------------
var context = canvas.getContext("2d");

// ------------------------------------------------------------
// 新しい ImageData オブジェクトを作成する
// ------------------------------------------------------------
var image_data = context.createImageData( 256 , 256 );

// ------------------------------------------------------------
// Uint8ClampedArray オブジェクトを取得する
// ------------------------------------------------------------
var ary_u8 = image_data.data;

// ------------------------------------------------------------
// ピクセルカラーを編集する
// ------------------------------------------------------------
var x;
var y;
var w = image_data.width;
var h = image_data.height;
for(y=0;y < h;y++){
	for(x=0;x < w;x++){

		// 各カラー
		var r = x;
		var g = 0;
		var b = y;
		var a = 255;

		// (x , y) の位置に書き込み
		var p = (y * w + x) * 4;
		ary_u8[p + 0] = r;
		ary_u8[p + 1] = g;
		ary_u8[p + 2] = b;
		ary_u8[p + 3] = a;
	}
}

// ------------------------------------------------------------
// ImageData オブジェクトを描画する
// ------------------------------------------------------------
context.putImageData( image_data , 0 , 0 );
 
ImageData オブジェクトのピクセルカラーを編集する(DataView)

// ------------------------------------------------------------
// HTMLCanvasElement オブジェクトを作成する
// ------------------------------------------------------------
var canvas = document.createElement("canvas");

// キャンバスのサイズを設定する
canvas.width  = 256;
canvas.height = 256;

// BODY のノードリストに登録する
document.body.appendChild(canvas);

// ------------------------------------------------------------
// CanvasRenderingContext2D オブジェクトを取得する
// ------------------------------------------------------------
var context = canvas.getContext("2d");

// ------------------------------------------------------------
// 新しい ImageData オブジェクトを作成する
// ------------------------------------------------------------
var image_data = context.createImageData( 256 , 256 );

// ------------------------------------------------------------
// Uint8ClampedArray オブジェクトを取得する
// ------------------------------------------------------------
var ary_u8 = image_data.data;

// ------------------------------------------------------------
// DataView オブジェクトを作成する
// ------------------------------------------------------------
var data_view = new DataView(ary_u8.buffer);

// ------------------------------------------------------------
// ピクセルカラーを編集する
// ------------------------------------------------------------
var x;
var y;
var w = image_data.width;
var h = image_data.height;
for(y=0;y < h;y++){
	for(x=0;x < w;x++){

		// 各カラー
		var r = x;
		var g = 0;
		var b = y;
		var a = 255;

		// RGBA カラー
		var color_rgba = (r << 24) | (g << 16) | (b << 8) | (a << 0);

		// (x , y) の位置に書き込み
		data_view.setUint32( (y * w + x) * 4 , color_rgba );
	}
}

// ------------------------------------------------------------
// ImageData オブジェクトを描画する
// ------------------------------------------------------------
context.putImageData( image_data , 0 , 0 );
 


 

ImageData オブジェクトにキャプチャする

 
 


■描画済みの結果を、ImageData 形式で取得する

 
getImageData() メソッドを使用します。
 
新しい ImageData オブジェクトが作成されます。
 
CanvasRenderingContext2D.getImageData ( sx , sy , sw , sh ) :ImageData
第01引数 Number水平方向の位置を指定。(Context2D の座標系)
第02引数 Number垂直方向の位置を指定。(Context2D の座標系)
第03引数 Number幅を指定。(ピクセル数)
第04引数 Number高さを指定。(ピクセル数)
戻り値 ImageData新しい ImageData オブジェクトが得られる。
 
■使用例
 
描画済みの結果を、ImageData 形式で取得する

// ------------------------------------------------------------
// HTMLCanvasElement オブジェクトを作成する
// ------------------------------------------------------------
var canvas = document.createElement("canvas");

// BODY のノードリストに登録する
document.body.appendChild(canvas);

// ------------------------------------------------------------
// CanvasRenderingContext2D オブジェクトを取得する
// ------------------------------------------------------------
var context = canvas.getContext("2d");

// ------------------------------------------------------------
// 矩形を描画する
// ------------------------------------------------------------
// 面の塗りを設定する(単一色)
context.fillStyle = "rgba(255,128,32,0.9)";

// 矩形を面描画する
context.fillRect( 0 , 0 , canvas.width , canvas.height );

// ------------------------------------------------------------
// 描画済みの結果を、ImageData 形式で取得する
// ------------------------------------------------------------
var image_data = context.getImageData( 0 , 0 , canvas.width , canvas.height );

// 出力テスト
console.log(image_data);
 


 

ImageData オブジェクトを描画する

 
 


■ ImageData オブジェクトを Context2D に高速転送する

 
putImageData() メソッドを使用します。
 
このメソッドは、引数の指定数によって、動作が変化します。
 
■ ImageData を Context2D に高速転送する(全体)
 
CanvasRenderingContext2D.putImageData ( imagedata , dx , dy ) :Void
第01引数 ImageDataソースとなる ImageData オブジェクトを指定。
第02引数 Number(描画位置) 水平方向の位置を指定。(Context2D の座標系)
第03引数 Number(描画位置) 垂直方向の位置を指定。(Context2D の座標系)
戻り値 Voidなし。
 
■ ImageData を Context2D に高速転送する(切り取り)
 
第04~07引数から、ImageData を切り抜く事ができます。
 
CanvasRenderingContext2D.putImageData ( imagedata , dx , dy , dirtyX , dirtyY , dirtyWidth , dirtyHeight ) :Void
第01引数 ImageDataソースとなる ImageData オブジェクトを指定。
第02引数 Number(描画位置) 水平方向の位置を指定。(Context2D の座標系)
第03引数 Number(描画位置) 垂直方向の位置を指定。(Context2D の座標系)
第04引数 Number(切り抜き) 水平方向の位置を指定。(テクスチャ座標系)
第05引数 Number(切り抜き) 垂直方向の位置を指定。(テクスチャ座標系)
第06引数 Number(切り抜き) 幅を指定。
第07引数 Number(切り抜き) 高さを指定。
戻り値 Voidなし。
 
■ putImageData() メソッドの動作について
 
イメージの描画ではない事に注意して下さい。
 
単純に、書き潰しコピーします。
 
アルファブレンドは行われません。
 
透明度の設定や、合成モードの設定は、無視されます。
 
トランスフォームの設定は、無視されます。
 
■使用例
 
ImageData オブジェクトを Context2D に高速転送する

// ------------------------------------------------------------
// HTMLCanvasElement オブジェクトを作成する
// ------------------------------------------------------------
var canvas = document.createElement("canvas");

// キャンバスのサイズを設定する
canvas.width  = 120;
canvas.height = 120;

// BODY のノードリストに登録する
document.body.appendChild(canvas);

// ------------------------------------------------------------
// CanvasRenderingContext2D オブジェクトを取得する
// ------------------------------------------------------------
var context = canvas.getContext("2d");

// ------------------------------------------------------------
// 矩形を描画する
// ------------------------------------------------------------
// 面の塗りを設定する(単一色)
context.fillStyle = "#f00";

// 矩形を面描画する
context.fillRect( 0 , 0 , canvas.width , canvas.height );

// ------------------------------------------------------------
// ImageData オブジェクトを作成する
// ------------------------------------------------------------
var image_data = context.createImageData( 256 , 256 );

// ------------------------------------------------------------
// ランダム値を書き込む(ノイズエフェクト)
// ------------------------------------------------------------
var ary_u8 = image_data.data;
var i;
var num = ary_u8.length;
for(i=0;i < num;i++){
	ary_u8[i] = Math.floor(Math.random() * 255);
}

// ------------------------------------------------------------
// 転送パラメータ
// ------------------------------------------------------------
// ソース側のクリッピングサイズ
var source_rect = { x:10 , y:10 , width:100, height:100 };

// ターゲット側の位置
var target_pos = { x:10 , y:10 };

// ------------------------------------------------------------
// ImageData オブジェクトを Context2D に高速転送する
// ------------------------------------------------------------
context.putImageData(
	image_data,
	target_pos.x - source_rect.x,
	target_pos.y - source_rect.y,
	source_rect.x,
	source_rect.y,
	source_rect.width,
	source_rect.height
);
 

■ ImageData オブジェクトをテクスチャとして活用する

 
ImageData オブジェクト自体は、テクスチャとして機能しません。
 
ImageData オブジェクトは、ImageBitmap オブジェクトに変換できます。
 
ImageBitmap 型であれば、テクスチャとして機能します。
 
■使用例
 
ImageData オブジェクトを ImageBitmap 型に変換して描画する

// ------------------------------------------------------------
// HTMLCanvasElement オブジェクトを作成する
// ------------------------------------------------------------
var canvas = document.createElement("canvas");

// キャンバスのサイズを設定する
canvas.width  = 512;
canvas.height = 512;

// BODY のノードリストに登録する
document.body.appendChild(canvas);

// ------------------------------------------------------------
// CanvasRenderingContext2D オブジェクトを取得する
// ------------------------------------------------------------
var context = canvas.getContext("2d");

// ------------------------------------------------------------
// 矩形を描画する
// ------------------------------------------------------------
// 面の塗りを設定する(単一色)
context.fillStyle = "#f00";

// 矩形を面描画する
context.fillRect( 0 , 0 , canvas.width , canvas.height );

// ------------------------------------------------------------
// ImageData オブジェクトを作成する
// ------------------------------------------------------------
var image_data = context.createImageData( 64 , 64 );

// ------------------------------------------------------------
// ランダム値を書き込む(ノイズエフェクト)
// ------------------------------------------------------------
var ary_u8 = image_data.data;
var i;
var num = ary_u8.length;
for(i=0;i < num;i++){
	ary_u8[i] = Math.floor(Math.random() * 255);
}

// ------------------------------------------------------------
// ImageBitmap オブジェクトを作成する
// ------------------------------------------------------------
// 実行を開始する
var promise = window.createImageBitmap(image_data);

// 結果を受け取る
promise.then(

	// ------------------------------------------------------------
	// 成功時に実行されるコールバック関数
	// ------------------------------------------------------------
	function success(image_bitmap){

		// ------------------------------------------------------------
		// 描画姿勢を設定する
		// ------------------------------------------------------------
		// 描画姿勢をリセットする
		context.setTransform( 1 , 0 , 0 , 1 , 0 , 0 );
		// 並行移動成分を合成
		context.translate( 256.0 , 256.0 );
		// 回転成分を合成
		context.rotate( 15.0 * (Math.PI / 180) );
		// 拡大縮小成分を合成
		context.scale( 5.0 , 5.0 );

		// ------------------------------------------------------------
		// イメージのスムージングを設定する
		// ------------------------------------------------------------
		context.imageSmoothingEnabled = false;

		// ------------------------------------------------------------
		// イメージを描画する
		// ------------------------------------------------------------
		context.drawImage( image_bitmap , -32 , -32 );

		// 出力テスト
		console.log(image_bitmap);
	},

	// ------------------------------------------------------------
	// 失敗時に実行されるコールバック関数
	// ------------------------------------------------------------
	function failure(){

	}
);