サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

EaselJS 0.7.0のColorMatrix.concat()メソッドが正しい演算結果を返さない

ID: FN1311001 Technique: HTML5 and JavaScript Library: EaselJS 0.7.0

EaselJS 0.7.0のColorMatrix.concat()メソッドは、引数に配列でなくColorMatrixオブジェクトを受取ったとき、正しく乗算された行列のオブジェクトを返しません。

The ColorMatrix.concat() method of EaselJS 0.7.0 does not return the correctly multiplied matrix

The ColorMatrix.concat() method of EaselJS 0.7.0 does not return the correctly multiplied matrix object when its received argument is not an Array but a ColorMatrix object.


01 問題 / Problem

以下のコードでは、参照したColorMatrixオブジェクトは、ColorMatrix.concat()メソッドでもうひとつのオブジェクトと演算(乗算)しても変わりません。もとのColorMatrixオブジェクトの25成分値はすべてそのままです。

In the code below the concatenated (multipled) matrix is not changed. The 25 factors of the first matrix are all kept inspite of multiplication by the second matrix.

var matrix = new createjs.ColorMatrix();
console.log(matrix.concat(new createjs.ColorMatrix(255)));
// [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1]

ColorMatrixオブジェクトのカラー変換行列を演算(乗算)した値は、つぎのようになるべきてす。

The multiplied matrix's values of the ColorMatrix objects should be as follows:

[1, 0, 0, 0, 255, 0, 1, 0, 0, 255, 0, 0, 1, 0, 255, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1]

02 原因 / Cause

まず、ColorMatrixクラスはFunction.prototypeプロパティにArrayオブジェクト(配列)を与えています。けれど、配列をクラスのプロトタイプオブジェクトに定めただけでは、Arrayクラスを完全に継承することはできません。

The first, the Function.prototype property of the ColorMatrix class is set to an Array object. But the Array class is not completely inherited just by this statement.

function ColorMatrix(brightness, contrast, saturation, hue) {
  this.initialize(brightness, contrast, saturation, hue);
};
ColorMatrix.prototype = [];

createjs.ColorMatrix.prototype.concat = function(matrix) {
  matrix = this._fixMatrix(matrix);
  if (matrix.length != ColorMatrix.LENGTH) { return this; }
  // ...[中略]...
};

つぎに、ColorMatrix.concat()メソッドは、内部的にColorMatrix._fixMatrix()メソッドを呼出します。そして、その引数がColorMatrixオブジェクトであれば、配列に変換されます。ColorMatrix._fixMatrix()メソッドは、引数のColorMatrixオブジェクトにArray.slice()メソッドを呼出して、カラー変換行列の成分値がエレメントに納められた配列を得ようとします。

The second, the ColorMatrix.concat() method internally calls ColorMatrix._fixMatrix() method. And its passed argument of a ColorMatrix object would be converted into an Array. The ColorMatrix._fixMatrix() calls the referenced object's Array.slice() method to get the Array containing the elements of the ColorMatrix object's factors.

  1. createjs.ColorMatrix.prototype._fixMatrix = function(matrix) {
  2.   if (matrix instanceof ColorMatrix) {
  3.     matrix = matrix.slice(0);
  1.   return matrix;
  2. };

ところが、呼出されたArray.slice()メソッドは空の配列を返します。Function.prototypeプロパティでArrayクラスを継承しただけでは、Array.lengthプロパティがデフォルト値の0のままだからです(「EaselJS 0.7.0: ColorMatrix.toArray()メソッドが空の配列を返す」参照)。ColorMatrix.concat()メソッドは、空の配列を引数に受取ると、参照したColorMatrixオブジェクトをそのまま返します(前掲ColorMatrix.concat()メソッドの実装参照)。

However the called Array.slice() method returns an empty Array object because the Array.length property of the ColorMatrix object remains 0 (cf. "EaselJS 0.7.0: ColorMatrix.toArray() returns an empty array"). The ColorMatrix.concat() method received an empty Array as its argument returns the referenced ColorMatrix object as it is (see the above code).


03 対処法 / Workaround

ColorMatrix.concat()メソッドの引数には配列を渡すべきでしょう。次期バージョン候補は、Arrayクラスを継承しないため、メソッドの引数にColorMatrixオブジェクトを渡せばエラーになります。ColorMatrix.concat()メソッドは、つぎのように修正するのがよいと思われます。

An Array object should be passed as the argument of the ColorMatrix.concat() method. The NEXT version of the class does not inherit the Array class. Therefore, a ColorMatrix object passed as the argument causes a type error. The ColorMatrix.concat() method might be fixed as follows:

  1. createjs.ColorMatrix.prototype._fixMatrix = function(matrix) {
  2.   if (matrix instanceof ColorMatrix) {
        // matrix = matrix.slice(0);
  3.     matrix = matrix.toArray();
  4.   }
  5.   if (matrix.length < ColorMatrix.LENGTH) {
  6.     matrix = matrix.slice(0, matrix.length).concat(ColorMatrix.IDENTITY_MATRIX.slice(matrix.length, ColorMatrix.LENGTH));
  7.   } else if (matrix.length > ColorMatrix.LENGTH) {
  8.     matrix = matrix.slice(0, ColorMatrix.LENGTH);
  9.   }
  10.   return matrix;
  11. };

[追記: 2013/11/20] EaselJS次期バージョンでColorMatrix.concat()メソッドは、上述の修正が加えられました

[PS: 2013/11/20] The ColorMatrix.concat() method of the EaselJS NEXT version is fixed in the way above.



作成者: 野中文雄
更新日: 2013年11月20日 [追記]の説明を更新。
更新日: 2013年11月18日 [追記]を加えた。
作成日: 2013年10月15日


Copyright © 2001-2013 Fumio Nonaka.  All rights reserved.