サイトトップ

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

HTML5テクニカルノート

EaselJS 0.7.0: バグが確認されているColorMatrixクラスのメソッド

ID: FN1311003 Technique: HTML5 and JavaScript Library: EaselJS 0.7.0 and NEXT

EaselJS 0.7.0のColorMatrixクラスには、すでにバグの確認されたメソッドがあります。そして、いくつかは次期バージョン候補(NEXT)で修正されました。ここでは3つのメソッドを、実装にも触れつつご紹介します。なお、ColorMatrixとColorMatrixFilterクラスを用いたオブジェクトのカラーの変換については、「EaselJSのフィルタColorMatrixFilterでイメージをセピア調に変える」をご参照ください。


01 ColorMatrix.toArray()メソッド

ColorMatrix.toArray()メソッドは、長さ(Array.lengthプロパティの値)が0の空の配列を返します。カラー変換行列は5行×5列の25成分をもちますので、戻り値の配列には25エレメントが含まれていなければなりません。ところが、ColorMatrix.toArray()メソッドが返す配列に、エレメントがひとつも入っていないのです。

EaselJS 0.7.0のColorMatrixクラスは、Arrayクラスのサブクラスとして定められています。しかし、Arrayクラスは、原則どおりのやり方で完全に継承することができません。そのため、ColorMatrix()コンストラクタでつくられたオブジェクトのArray.lengthプロパティは0のままになっています(「EaselJS 0.7.0: ColorMatrix.toArray()メソッドが空の配列を返す」参照)。

ColorMatrix.toArray()メソッドを呼出す前に、ColorMatrixオブジェクトのArray.lengthプロパティを正しく25に定めると、メソッドの戻り値として25エレメントの配列が得られます。ただし、Arrayクラスが、これですべて継承できたわけではありません。なお、ColorMatrixオブジェクトの成分数25は、内部的に定数ColorMatrix.LENGTHとして備えられています。

  1. var matrix = new createjs.ColorMatrix();
  2. matrix.length = createjs.ColorMatrix.LENGTH;
  3. var _array = matrix.toArray();
    // [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]

EaselJS 0.7.0のColorMatrix.toArray()メソッドは、実質的につぎのように実装されています。ColorMatrix()コンストラクタ関数のFunction.prototypeプロパティにArrayオブジェクト(配列)を与えています(第4行目)。これでそのオブジェクトのクラスは継承できるのが原則です。ところが、前述のとおりArray.lengthプロパティが正しい値に書替えられないため、ColorMatrix.toArray()メソッドから内部的に呼出されるArray.slice()メソッドが25成分値を取出せません。

  1. function ColorMatrix(brightness, contrast, saturation, hue) {
  2.   this.initialize(brightness, contrast, saturation, hue);
  3. }
  4. ColorMatrix.prototype = [];
  1. ColorMatrix.prototype.toArray = function() {
  2.   return this.slice(0, ColorMatrix.LENGTH);
  3. };

次期バージョンのColorMatrixクラスは、Arrayクラスを継承しなくなります。そこで、ColorMatrix.toArray()メソッドは、ColorMatrixオブジェクトがもつカラー変換行列の成分値をforループで取出して、新たな配列に納めたうえで返すように修正されました(第2〜6行目)。

  1. ColorMatrix.prototype.toArray = function() {
      // return this.slice(0, ColorMatrix.LENGTH);
  2.   var arr = [];
  3.   for (var i = 0, l = ColorMatrix.LENGTH; i < l; i++) {
  4.     arr[i] = this[i];
  5.   }
  6.   return arr;
  7. };

02 ColorMatrix.concat()メソッド

ColorMatrix.concat()メソッドは、引数にColorMatrixオブジェクトを受取ると行列演算はせずに、メソッドが参照したColorMatrixオブジェクトをそのまま返します。ColorMatrix.concat()メソッドの引数にはColorMatrixオブジェクトでなく、必ず配列でカラー変換行列の成分値を渡すのがよいでしょう(図001)。

図001■リファレンスのColorMatrix.concat()メソッドの説明
図001

ColorMatrix.concat()メソッドは、実質的につぎのように実装されています。引数(matrix)は、まずカラー変換行列の25成分をエレメントに納めた配列にするため、ColorMatrix._fixMatrix()メソッドに渡されます(第6行目)。つぎに、ColorMatrix._fixMatrix()メソッドは引数がColorMatrixインスタンスのときは、そのオブジェクトを参照してArray.slice()メソッドの呼出しにより配列に換えようとします(第10〜12行目)。

ところが、前項で述べたとおり、ColorMatrixオブジェクトのArray.lengthプロパティが0であるため、Array.slice()メソッドは空の配列を返してしまいます。そして、空の配列をColorMatrix.concat()メソッドで演算しようとすれば、メソッドが参照したColorMatrixオブジェクトがそのまま返されるのです(第7行目)。

  1. function ColorMatrix(brightness, contrast, saturation, hue) {
  2.   this.initialize(brightness, contrast, saturation, hue);
  3. };
  4. ColorMatrix.prototype = [];
  1. createjs.ColorMatrix.prototype.concat = function(matrix) {
  2.   matrix = this._fixMatrix(matrix);
  3.   if (matrix.length != ColorMatrix.LENGTH) { return this; }
  1. };
  2. createjs.ColorMatrix.prototype._fixMatrix = function(matrix) {
  3.   if (matrix instanceof ColorMatrix) {
  4.     matrix = matrix.slice(0);
  5.   };
  1.   return matrix;
  2. };

前述のとおり、次期バージョンのColorMatrixクラスは、Arrayクラスを継承しません。また、ColorMatrix.toArray()メソッドは正しく25エレメントの配列を返します。そこで、ColorMatrix.concat()メソッドはつぎのように修正されました

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

03 ColorMatrix.clone()メソッド

ColorMatrix.clone()メソッドは呼出すと環境によってはエラーを起こし、いずれにしても正しく複製されたColorMatrixオブジェクトは返しません。コンストラクタで新たなColorMatrixオブジェクトをつくって、ColorMatrix.copyMatrix()メソッドでカラー変換行列の成分値をコピーするのがよいです。

    // var clone = matrix.clone();
  1. var clone = new createjs.ColorMatrix();
  2. clone.copyMatrix(matrix);

ColorMatrix.clone()メソッドは、実質的につぎのように実装されています。内部的に呼出しているColorMatrix()コンストラクタに渡す引数は、ColorMatrixオブジェクトひとつでなく4つの数値でなければなりません(第10行目)。引数の数やそのデータの型が違っているので、正しくオブジェクトを返さないのです。

  1. function ColorMatrix(brightness, contrast, saturation, hue) {
  2.   this.initialize(brightness, contrast, saturation, hue);
  3. }
  4. ColorMatrix.prototype.initialize = function(brightness, contrast, saturation, hue) {
  5.   this.reset();
  6.   this.adjustColor(brightness, contrast, saturation, hue);
  7.   return this;
  8. };
  1. ColorMatrix.prototype.clone = function() {
  2.   return new ColorMatrix(this);
  3. };

次期バージョンのColorMatrix.clone()メソッドは、コンストラクタでつくった新たなColorMatrixオブジェクトに、ColorMatrix.copyMatrix()メソッドでカラー変換行列の成分値をコピーするように修正されました

  1. ColorMatrix.prototype.clone = function() {
      // return new ColorMatrix(this);
  2.   return (new ColorMatrix()).copyMatrix(this);
  3. };


作成者: 野中文雄
作成日: 2013年11月29日


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