BitmapData for EaselJSの使い方

こんにちわ。最近、梅干しを1日1個食べることを日課にしているkudoxです。今回は、先日公開したBitmapData for EaselJSの使い方を簡単なサンプルと共に紹介したいと思います。BitmapData for EaselJSは、基本的にActionScript3.0に合わせて作っているので、Flashをやられている方は違和感なく使うことができると思います。

追記 2013/10/22

BitmapData for EaselJS ver1.00で追加したapplyFilter, expand, perlinNoiseについては、「BitmapData for EaselJS ver1.00 リリースのお知らせ」で解説していますので、こちらをご覧下さい。

BitmapDataインスタンスを作成する

BitmapDataインスタンスは、コンストラクタにより作成することができます。第1引数に読み込みの終わったHTMLImageElementを渡すと、その画像のBitmapDataインスタンスが作成されます。第1引数にはHTMLImageElementだけでなく、HTMLCanvasElement, HTMLVideoElementを指定することもできます。

塗りのBitmapDataを作成したい場合は、第1引数をnullにして第2引数以降でwidth, height, fillColorを指定します。fillColorの指定は、CSS文字列と0xAARRGGBB形式の16進数値が使えます。

BitmapDataインスタンスをStage上に表示するにはBitmapクラスを使いますが、BitmapクラスのコンストラクタにはBitmapDataインスタンスではなく、BitmapDataインスタンスのcanvasプロパティを渡す点にはご注意下さい。

JavaScript

var image = _image01;
_bmd01 = new createjs.BitmapData(image);
_bitmap01 = new createjs.Bitmap(_bmd01.canvas);
_stage.addChild(_bitmap01);
var width = 200;
var height = 200;
var fillColor = 0x80FF0000;
_bmd02 = new createjs.BitmapData(null, width, height, fillColor);
_bitmap02 = new createjs.Bitmap(_bmd02.canvas);
_stage.addChild(_bitmap02);

DisplayObjectからBitmapDataを取得する

BitmapDataクラスのstaticメソッドgetBitmapData()を使うことにより、cache()されたDisplayObject及びそのサブクラスのインスタンスをBitmapDataとして取得することができます。getBitmapData()で得られるBitmapDataは、DisplayObjectのcacheの参照です。DisplayObject側でupdateCache()を実行した場合は、取得したBitmapDataも更新される点にはご注意下さい。

JavaScript

_shape = new createjs.Shape();
var g = _shape.graphics;
g.f("rgba(0,0,255,1)").dp(0, 0, 100, 5, 0.6, -90).ef();
_shape.x = _canvas.width >> 1;
_shape.y = _canvas.height >> 1;
_shape.cache(-100, -100, 200, 200);
_bmd01 = createjs.BitmapData.getBitmapData(_shape);
var colorTransform = new createjs.ColorTransform(1, 1, 0, 1, 255);
var rect = new createjs.Rectangle(0, 0, _bmd01.width >> 1, _bmd01.height);
_bmd01.colorTransform(rect, colorTransform);
_stage.addChild(_shape);

colorTransform()

colorTransform()を使うとBitmapDataのカラー値を調整することができます。第1引数でカラーを調整する領域をRectangleで指定し、第2引数でColorTransformインスタンスを指定します。ColorTransformコンストラクタの引数は、順番にredMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier, redOffset, greenOffset, blueOffset, alphaOffsetとなります。下記のサンプルでは、画像の右側半分のカラー値を調整しています。

JavaScript

_bmd01 = new createjs.BitmapData(_image01);
var halfW = _image01.width >> 1;
var rect = new createjs.Rectangle(halfW, 0, halfW, _image01.height);
var colorTransform = new createjs.ColorTransform(0.5, 1.5, 1.5);
_bmd01.colorTransform(rect, colorTransform);

compare()

compare()は、現在のBitmapDataと引数で渡されたオブジェクトを比較します。指定できるオブジェクトは、BitmapData, HTMLCanvasElement, HTMLImageElement, HTMLVideoElement, createjs.Stage, cache()されたcreatejs.DisplayObjectのサブクラスです。

戻り値に関しては、ActionScript3.0に合わせていますので、ActionScript3.0 リファレンスをご覧頂くと良いかも知れません。下記のサンプルでは、左右に配置した画像の差分として取得したBitmapDataを中央に表示しています。

JavaScript

_bmd01 = new createjs.BitmapData(_image01);
_bmd03 = new createjs.BitmapData(_image02);
var otherSource = _bmd03;
_bmd02 = _bmd01.compare(otherSource);
_bitmap01 = new createjs.Bitmap(_bmd01.canvas);
_bitmap02 = new createjs.Bitmap(_bmd02.canvas);
_bitmap03 = new createjs.Bitmap(_bmd03.canvas);
_bitmap01.x = 10;
_bitmap02.x = 220;
_bitmap03.x = 430;
_bitmap01.y = _bitmap02.y = _bitmap03.y = 80;

copyChannel()

copyChannel()は、第1引数で渡されたソースオブジェクトのチャンネルを現在のBitmapDataのチャンネルに転送します。指定できるオブジェクトは、BitmapData, HTMLCanvasElement, HTMLImageElement, HTMLVideoElement, createjs.Stage, cache()されたcreatejs.DisplayObjectのサブクラスです。

第2引数はソースオブジェクトの範囲を示すRectangle、第3引数はデータが配置される左上の座標を示すPoint、第4引数でソースのチャンネル、第5引数で転送先のチャンネルを指定します。チャンネルの指定には、BitmapDataChannelクラスの定数が使えます。下記のサンプルでは、ソース画像のアルファチャンネルをターゲットBitmapDataの青チャンネルに転送しています。

JavaScript

_bmd01 = new createjs.BitmapData(_image01);
var source = _image02;
var sourceRect = new createjs.Rectangle(0, 0, _image02.width, _image02.height);
var destPoint = new createjs.Point();
var channel = Object.create(createjs.BitmapDataChannel);
var sourceChannel = channel.ALPHA;
var destChannel = channel.BLUE;
_bmd01.copyChannel(source, sourceRect, destPoint, sourceChannel, destChannel);

copyPixels()

copyPixels()は、第1引数で渡されたソースオブジェクトを現在のBitmapDataに貼り付けます。指定できるオブジェクトは、BitmapData, HTMLCanvasElement, HTMLImageElement, HTMLVideoElement, createjs.Stage, cache()されたcreatejs.DisplayObjectのサブクラスです。

第2引数はソースオブジェクトの範囲を示すRectangle、第3引数は貼り付け先の左上座標を示すPointです。第4引数以降はオプションで、ソースオブジェクトのアルファチャンネルとして使用するオブジェクトを指定することができます。第4引数でアルファチャンネルのソースとなるオブジェクト、第5引数でそのオブジェクトの左上座標を示すPoint、第6引数でアルファチャンネルを使用するかどうかをBool値で指定します。

言葉の説明だとわかりにくいので、実際にサンプルを見た方がわかりやすいでしょう。下記のサンプルでは3つのcopyPixels()の実行結果を並べていますが、左からalphaSource無し、alphaSource有り、alphaSource有りでアルファチャンネル使用になります。

JavaScript

_bmd01 = new createjs.BitmapData(null, 640, 360, 0xCCCCCC);
var source = _image01;
var sourceRect = new createjs.Rectangle(0, 0, _image01.width, _image01.height);
var destPoint;
var alphaSource = _maskImage;
var alphaPoint = new createjs.Point();
var mergeAlpha = true;
destPoint = new createjs.Point(10, 80);
_bmd01.copyPixels(source, sourceRect, destPoint);
destPoint = new createjs.Point(220, 80);
_bmd01.copyPixels(source, sourceRect, destPoint, alphaSource);
destPoint = new createjs.Point(430, 80);
_bmd01.copyPixels(source, sourceRect, destPoint, alphaSource, alphaPoint, mergeAlpha);

draw()

draw()は、第1引数で渡されたソースオブジェクトを現在のBitmapDataに描画します。指定できるオブジェクトは、BitmapData, HTMLCanvasElement, HTMLImageElement, HTMLVideoElement, createjs.Stage, cache()されたcreatejs.DisplayObjectのサブクラスです。

第2引数でソースオブジェクトの変換行列、第3引数でColorTransformオブジェクトを指定できます。第4引数はFlashではblendModeの指定ですが、BitmapData for EaselJSではCanvasのglobalCompositeOperationの値となります。globalCompositeOperationの値に関しては、HTML5.JPのCanvasリファレンスが参考になるかと思います。

第5引数はクリッピング領域を示すRectangle、第6引数はスムージングを行うかBool値で指定します。下記のサンプルでは、星形のShapeインスタンスからBitmapDataを取得し、matrixやcolorTransformを変えながら1枚のBitmapDataに連続的に描画しています。

JavaScript

var matrix = new createjs.Matrix2D(1, 0, 0, 1, -_sourceRect.width >> 1, -_sourceRect.height >> 1);
var rotation = Math.random() * 360 >> 0;
matrix.rotate(rotation * createjs.Matrix2D.DEG_TO_RAD);
var scale = Math.random() * 0.5 + 0.5;
matrix.prepend(scale, 0, 0, scale, 0, 0);
var tx = Math.random() * _bmd01.width >> 0;
var ty = Math.random() * _bmd01.height >> 0;
matrix.translate(tx, ty);
var red = (Math.random() * 224 >> 0) + 32;
var green = (Math.random() * 224 >> 0) + 32;
var blue = (Math.random() * 224 >> 0) + 32;
var colorTransform = new createjs.ColorTransform(0, 0, 0, 1, red, green, blue);
var compositeOperation = "lighter";
var clipRect = null;
var smoothing = true;
_bmd01.draw(_source, matrix, colorTransform, compositeOperation, clipRect, smoothing);

fillRect()

fillRect()は、第1引数で指定されたRectangleの領域を第2引数のカラー値で塗りつぶします。カラー値の指定は、CSS文字列と0xAARRGGBB形式の16進数値が使えます。また、BitmapData for EaselJSではclearRect()も定義しています。clearRect()の引数はx, y, width, heightで、指定した領域が透明な黒になります。

JavaScript

_bmd01 = new createjs.BitmapData(null, 200, 200);
_bmd02 = _bmd01.clone();
var rect = new createjs.Rectangle(0, 0, 200, 200);
var color01 = 0x80FF0000;
_bmd01.fillRect(rect, color01);
var color02 = createjs.Graphics.getRGB(0, 0, 255, 0.5)
_bmd02.fillRect(rect, color02);
var x = 50;
var y = 50;
var width = 100;
var height = 100;
_bmd01.clearRect(x, y, width, height);
_bmd02.clearRect(x, y, width, height);

floodFill()

floodFill()は、第1, 2引数でx, y座標を指定し、第3引数でカラー値を指定することにより、上下左右に連続した色をバケツツールのように塗りつぶすことができます。カラー値の指定は、0xAARRGGBB形式の16進数値のみでCSS文字列は使えません。下記のサンプルでは、stage上をクリックすることにより、ランダムに描画された矩形をfloodFill()で塗りつぶしています。

JavaScript

function clickHandler(evt) {
  _bmd01.floodFill(evt.stageX, evt.stageY, 0xFFCCCCCC);
  _stage.update();
}

getPixel(), setPixel()

getPixel()は、引数で指定したx, y座標のRGB値を数値で返します。setPixel()は、第1, 2引数で指定した座標のカラーを第3引数のカラー値に設定します。カラー値の指定は、0xRRGGBB形式の16進数値のみでCSS文字列は使えません。

ActionScript3.0では、処理の高速化のためにlock()とunlock()が用意されていますが、BitmapData for EaselJSでは少し仕様が異なります。BitmapData for EaselJSでは常にlock()された状態で、unlock()の代わりになるのがupdateContext()です。updateContext()を実行することにより、setPixel()やsetPixel32()で行った処理がBitmapDataに反映されます。

JavaScript

var w = this.stageW;
var h = this.stageH;
var bmd = this.bmd;
var forcemap = this.forcemap;
bmd.fillRect(this.rect, 0xEE000000);
var channelX = this.channelX;
var channelY = this.channelY;
var particles = this.particles;
for (var i = 0, l = particles.length; i < l; i++) {
  var p = particles[i];
  var color = forcemap.getPixel(p.x, p.y);
  var cx = color >> channelX & 0xFF;
  var cy = color >> channelY & 0xFF;
  p.ax += (cx - 128) * 0.0005;
  p.ay += (cy - 128) * 0.0005;
  p.sx += p.ax;
  p.sy += p.ay;
  p.x += p.sx;
  p.y += p.sy;
  p.ax *= 0.96;
  p.ay *= 0.96;
  p.sx *= 0.92;
  p.sy *= 0.92;
  if (p.x < 0) {
    p.x = w - 1;
  } else if (w <= p.x) {
    p.x = 0;
  }
  if (p.y < 0) {
    p.y = h - 1;
  } else if (h <= p.y) {
    p.y = 0;
  }
  bmd.setPixel(p.x, p.y, 0x0099FF);
}
bmd.updateContext();

getPixels(), setPixels()

getPixels()を使うと引数のRectangleで指定した領域のピクセルデータを配列に似た形式で取得することができます。戻り値のピクセルデータは、ActionScript3.0ではA, R, G, Bの並びですが、BitmapData for EaselJSではR, G, B, Aの並びになっていますので、ご注意下さい。

setPixels()は、第1引数のRectangleで指定された領域のピクセルデータを第2引数で指定された配列のデータで差し替えます。getPixels()と同様にピクセルの並びはR, G, B, Aの順番になります。

下記のサンプルでは、getPixels()でピクセルデータを取得し、X座標が奇数のピクセルのみ別の画像のデータに変更して、setPixels()で差し替えています。

JavaScript

_bmd01 = new createjs.BitmapData(_image01);
_bmd02 = new createjs.BitmapData(_image02);
var rect = new createjs.Rectangle(20, 20, 160, 160);
var data01 = _bmd01.getPixels(rect);
var data02 = _bmd02.getPixels(rect);
for (var i = 0, l = data01.length; i < l; i += 4) {
  if (i / 4 % 2 !== 0) {
    var r = i;
    var g = i + 1;
    var b = i + 2;
    var a = i + 3;
    data01[r] = data02[r];
    data01[g] = data02[g];
    data01[b] = data02[b];
    data01[a] = data02[a];
  }
}
_bmd01.setPixels(rect, data01);

hitTest()

hitTest()は、アルファチャンネルを含めたピクセルレベルの衝突判定を行います。第1引数で任意の座標空間における現在のBitmapDataの座標、第2引数で現在のBitmapDataで不透明とするアルファチャンネルのしきい値を指定します。

第3引数では衝突判定の対象となるオブジェクトを指定します。指定できるオブジェクトは、createjs.Point, createjs.Rectangle, BitmapData, HTMLCanvasElement, HTMLImageElement, HTMLVideoElement, createjs.Stage, cache()されたcreatejs.DisplayObjectのサブクラスです。

第4引数以降は対象オブジェクトがPoint, Rectangleの場合には必要ありません。第4引数で対象オブジェクトの座標、第5引数で対象オブジェクトで不透明とするアルファチャンネルのしきい値を指定します。

JavaScript

var firstPoint = new createjs.Point(_bitmap01.x, _bitmap01.y);
var firstAlphaThreshold = 0xFF;
var secondObject = _shape_bmd;
var secondObjectPoint = new createjs.Point(_shape.x -20, _shape.y -20);
var secondAlphaThreshold = 0x80;
if (_bmd01.hitTest(firstPoint, firstAlphaThreshold, secondObject, secondObjectPoint, secondAlphaThreshold)) {
  if (!_isHitting) {
    changeColor("rgba(0,255,0,0.75)");
  }
} else {
  if (_isHitting) {
    changeColor("rgba(0,0,255,0.75)");
  }
}

merge()

merge()は、現在のBitmapDataと第1引数で指定されたオブジェクトをチャンネルごとにブレンドします。指定できるオブジェクトは、BitmapData, HTMLCanvasElement, HTMLImageElement, HTMLVideoElement, createjs.Stage, cache()されたcreatejs.DisplayObjectのサブクラスです。

第2引数はソースオブジェクトの範囲を示すRectangle、第3引数はマージ先の座標を示すPointを指定します。第4引数以降では、R, G, B, Aの順にそれぞれのチャンネルに対して使用する乗数を指定することができます。下記のサンプルでは、左右に配置した画像のマージ結果を中央に表示しています。

JavaScript

_bmd01 = new createjs.BitmapData(_image01);
_bmd02 = _bmd01.clone();
_bmd03 = new createjs.BitmapData(_image02);
var source = _bmd03;
var sourceRect = new createjs.Rectangle(0, 0, _image02.width, _image02.height);
var destPoint = new createjs.Point();
var redMultiplier = 192;
var greenMultiplier = 64;
var blueMultiplier = 128;
var alphaMultiplier = 128;
_bmd02.merge(source, sourceRect, destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier);

noise()

noise()を使うとランダムノイズを生成することができます。ActionScript3.0では第1引数でrandomSeed(乱数の種)を指定することができますが、BitmapData for EaselJSでは常にランダムなノイズとなります。

第1引数は各チャンネルの最小値、第2引数は各チャンネルの最大値となります。第3引数で対象のチャンネルを指定することができます。チャンネルの指定には、BitmapDataChannelクラスの定数が使え、OR論理演算子で複数のチャンネルを組み合わせることもできます。

第4引数では、ノイズをグレースケールにするかをBool値で指定します。trueにした場合、アルファチャンネルを除いたすべてのチャンネルが同じ値となります。

JavaScript

_bmd01 = new createjs.BitmapData(null, 200, 200);
var low = 128;
var high = 200;
var channel = Object.create(createjs.BitmapDataChannel);
var channelOptions = channel.BLUE | channel.ALPHA;
var grayScale = false;
_bmd01.noise(low, high, channelOptions, grayScale);

paletteMap()

paletteMap()は、引数で渡されたカラーパレットデータ配列を使用して、BitmapDataのカラー値をマッピングします。第1引数でソースオブジェクトを指定します。指定できるオブジェクトは、BitmapData, HTMLCanvasElement, HTMLImageElement, HTMLVideoElement, createjs.Stage, cache()されたcreatejs.DisplayObjectのサブクラスです。

第2引数はソースオブジェクトの範囲を示すRectangle、第3引数はマッピング先の左上座標を示すPointです。第4引数以降で各チャンネルのパレットデータ配列をR, G, B, Aの順番で指定します。パレットデータ配列でnullを指定したチャンネルでは、ソースオブジェクトのチャンネルが使用されます。

下記のサンプルでは、画像の中央部分の色を反転させています。

JavaScript

_bmd01 = new createjs.BitmapData(_image01);
var source = _bmd01;
var sourceRect = new createjs.Rectangle(64, 48, 256, 144);
var destPoint = new createjs.Point(sourceRect.x, sourceRect.y);
var redArray = [], greenArray = [], blueArray = [], alphaArray = null;
for (var i = 0, l = 256; i < l; i++) {
  redArray[i] = (255 - i) << 16;
  greenArray[i] = (255 - i) << 8;
  blueArray[i] = 255 - i;
}
_bmd01.paletteMap(source, sourceRect, destPoint, redArray, greenArray, blueArray, alphaArray);

pixelDissolve()

pixelDissolve()を使うと現在のBitmapDataからソースオブジェクトへのピクセルディゾルブを実行することができます。第1引数でソースオブジェクトを指定します。指定できるオブジェクトは、BitmapData, HTMLCanvasElement, HTMLImageElement, HTMLVideoElement, createjs.Stage, cache()されたcreatejs.DisplayObjectのサブクラスです。

第2引数はソースオブジェクトの範囲を示すRectangle、第3引数はディゾルブ先の左上座標を示すPointです。第4引数はActionScript3.0ではrandomSeedですが、BitmapData for EaselJSではbuffer配列となります。pixelDissolve()の戻り値を指定することで連続したピクセルディゾルブを実行できる点は同じです。

第5引数は、1回の処理で置き換えるピクセル数、第6引数では現在のBitmapDataとソースオブジェクトが等しい場合に使用されるカラー値を0xAARRGGBB形式の16進数値で指定します。

JavaScript

function tickHandler(evt) {
  if (_buffer === 0) {
    return;
  }
  var sourceRect = new createjs.Rectangle(0, 0, _source.width, _source.height);
  var destPoint = new createjs.Point(sourceRect.x, sourceRect.y);
  var numPixels = 600;
  var fillColor = null
  _buffer = _bmd01.pixelDissolve(_source, sourceRect, destPoint, _buffer, numPixels, fillColor);
  _stage.update();
}

threshold()

threshold()は、引数のしきい値でBitmapDataのピクセル値をテストし、その合否によってピクセルに新たなカラー値をセットします。第1引数でソースオブジェクトを指定します。指定できるオブジェクトは、BitmapData, HTMLCanvasElement, HTMLImageElement, HTMLVideoElement, createjs.Stage, cache()されたcreatejs.DisplayObjectのサブクラスです。

第2引数はソースオブジェクトの範囲を示すRectangle、第3引数はピクセルの置き換え先の左上座標を示すPointです。第4引数ではピクセルのテストに使う比較演算子を文字列で指定します。指定することができる値は、"<", "<=", ">", ">=", "==", "!="です。

第5引数はしきい値となるカラー値、第6引数はテストに合格した際にセットされる新しいカラー値、第7引数は比較の範囲を設定するマスク値を指定します。カラー値の指定は、0xAARRGGBB形式の16進数値のみでCSS文字列は使えません。

第8引数では、比較結果がfalseの場合にソースオブジェクトのピクセルを現在のBitmapDataにコピーするかをBool値で指定します。

JavaScript

_bmd01 = new createjs.BitmapData(_image01);
var source = _bmd01;
var halfW = _bmd01.width >> 1;
var sourceRect = new createjs.Rectangle(halfW, 0, halfW, _bmd01.height);
var destPoint = new createjs.Point(sourceRect.x, sourceRect.y);
var operation = "<";
var threshold = 0xFFEE0000;
var color = 0x00000000;
var mask = 0xFFFF0000;
var copySource = false;
_bmd01.threshold(source, sourceRect, destPoint, operation, threshold, color, mask, copySource);